blob: 9762da26977d10bd8c0058510d1691bf9821e3a3 [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)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000429 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400430
npujarec5762e2020-01-01 14:08:48 +0530431 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficShaping, TrafficSched); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000432 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 -0400433 }
434
salmansiddiqui7ac62132019-08-22 03:58:50 +0000435 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400436 * store the meter id on the KV store, for further reference.
437 */
npujarec5762e2020-01-01 14:08:48 +0530438 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 +0000439 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 -0400440 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000441 logger.Debugw("updated-meter-info into KV store successfully", log.Fields{"Direction": Direction,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400442 "Meter": meterConfig})
443 return nil
444}
445
npujarec5762e2020-01-01 14:08:48 +0530446func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficShaping *tp_pb.TrafficShapingInfo, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000447
448 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
449
450 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000451 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 +0000452 }
453
Girish Kumar2ad402b2020-03-20 19:45:12 +0000454 logger.Debugw("Sending Traffic scheduler create to device", log.Fields{"Direction": sq.direction, "TrafficScheds": TrafficSched})
npujarec5762e2020-01-01 14:08:48 +0530455 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000456 IntfId: sq.intfID, OnuId: sq.onuID,
457 UniId: sq.uniID, PortNo: sq.uniPort,
458 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000459 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000460 }
461
462 // On receiving the CreateTrafficQueues request, the driver should create corresponding
463 // downstream queues.
Girish Kumar2ad402b2020-03-20 19:45:12 +0000464 logger.Debugw("Sending Traffic Queues create to device", log.Fields{"Direction": sq.direction, "TrafficQueues": trafficQueues})
npujarec5762e2020-01-01 14:08:48 +0530465 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000466 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
467 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000468 TrafficQueues: trafficQueues,
469 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000470 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"TrafficQueues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000471 }
472
Esin Karamanccb714b2019-11-29 15:02:06 +0000473 if sq.direction == tp_pb.Direction_DOWNSTREAM {
474 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(sq.tpInst)
475 if len(multicastTrafficQueues) > 0 {
476 if _, present := f.interfaceToMcastQueueMap[sq.intfID]; !present {
477 //assumed that there is only one queue per PON for the multicast service
478 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
479 //just put it in interfaceToMcastQueueMap to use for building group members
480 multicastQueuePerPonPort := multicastTrafficQueues[0]
481 f.interfaceToMcastQueueMap[sq.intfID] = &queueInfoBrief{
482 gemPortID: multicastQueuePerPonPort.GemportId,
483 servicePriority: multicastQueuePerPonPort.Priority,
484 }
485 //also store the queue info in kv store
npujarec5762e2020-01-01 14:08:48 +0530486 f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID,
Esin Karamanccb714b2019-11-29 15:02:06 +0000487 multicastQueuePerPonPort.GemportId,
488 multicastQueuePerPonPort.Priority)
489 }
490 }
491 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000492 return nil
493}
494
salmansiddiqui7ac62132019-08-22 03:58:50 +0000495// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530496func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400497
498 var Direction string
499 var SchedCfg *tp_pb.SchedulerConfig
500 var err error
Girish Kumar2ad402b2020-03-20 19:45:12 +0000501 logger.Debugw("Removing schedulers and Queues in OLT", log.Fields{"Direction": sq.direction, "IntfID": sq.intfID,
Gamze Abakafee36392019-10-03 11:17:24 +0000502 "OnuID": sq.onuID, "UniID": sq.uniID, "UniPort": sq.uniPort})
503 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000504 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400505 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000506 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000507 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400508 Direction = "downstream"
509 }
510
Girish Kumar8f73fe02019-12-09 13:19:37 +0000511 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000512 return olterrors.NewErrNotFound("scheduler-config", log.Fields{"IntID": sq.intfID, "Direction": sq.direction}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000513 }
514
npujarec5762e2020-01-01 14:08:48 +0530515 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400516 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000517 return olterrors.NewErrNotFound("meter", log.Fields{"onuID": sq.onuID}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400518 }
519 if KVStoreMeter == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000520 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 -0400521 return nil
522 }
523 cir := KVStoreMeter.Bands[0].Rate
524 cbs := KVStoreMeter.Bands[0].BurstSize
525 eir := KVStoreMeter.Bands[1].Rate
526 ebs := KVStoreMeter.Bands[1].BurstSize
527 pir := cir + eir
528 pbs := cbs + ebs
529
530 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
531
Gamze Abakafee36392019-10-03 11:17:24 +0000532 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000533 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000534
535 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
536 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000537 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 +0000538 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400539
npujarec5762e2020-01-01 14:08:48 +0530540 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000541 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
542 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000543 TrafficQueues: TrafficQueues,
544 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000545 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
546 log.Fields{"intfID": sq.intfID, "TrafficQueues": TrafficQueues}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400547 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000548 logger.Debug("Removed traffic queues successfully")
npujarec5762e2020-01-01 14:08:48 +0530549 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000550 IntfId: sq.intfID, OnuId: sq.onuID,
551 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400552 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000553 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
554 log.Fields{"intfID": sq.intfID, "TrafficSchedulers": TrafficSched}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400555 }
556
Girish Kumar2ad402b2020-03-20 19:45:12 +0000557 logger.Debug("Removed traffic schedulers successfully")
salmansiddiqui7ac62132019-08-22 03:58:50 +0000558
559 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400560 * delete the meter id on the KV store.
561 */
npujarec5762e2020-01-01 14:08:48 +0530562 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400563 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000564 return olterrors.NewErrAdapter("unable-to-remove-meter", log.Fields{"onu": sq.onuID, "meter": KVStoreMeter.MeterId}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400565 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000566 logger.Debugw("Removed-meter-from-KV-store successfully", log.Fields{"MeterId": KVStoreMeter.MeterId, "dir": Direction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400567 return err
568}
569
Gamze Abakafee36392019-10-03 11:17:24 +0000570// This function allocates tconts and GEM ports for an ONU
npujarec5762e2020-01-01 14:08:48 +0530571func (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 +0000572 var allocIDs []uint32
573 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530574 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530575 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000576 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000577
npujarec5762e2020-01-01 14:08:48 +0530578 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
579 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400580
581 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530582
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700583 logger.Infow("creating-new-tcont-and-gem", log.Fields{
584 "pon": intfID, "onu": onuID, "uni": uniID,
585 "deviceId": f.deviceHandler.device.Id, "tpId": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530586
Manikkaraj kb1d51442019-07-23 10:41:02 -0400587 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530588 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000589 if techProfileInstance == nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700590 logger.Infow("tp-instance-not-found--creating-new", log.Fields{"path": tpPath, "deviceId": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530591 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000592 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530593 // This should not happen, something wrong in KV backend transaction
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700594 logger.Errorw("tp-instance-create-failed", log.Fields{"error": err, "tpID": TpID, "deviceId": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000595 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530596 }
npujarec5762e2020-01-01 14:08:48 +0530597 f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530598 } else {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700599 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 +0530600 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530601 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400602 if UsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000603 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
604 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
npujarec5762e2020-01-01 14:08:48 +0530605 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700606 logger.Errorw("CreateSchedulerQueues Failed-upstream", log.Fields{"error": err, "meterID": UsMeterID, "deviceId": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000607 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400608 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530609 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400610 if DsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000611 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
612 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
npujarec5762e2020-01-01 14:08:48 +0530613 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700614 logger.Errorw("CreateSchedulerQueues Failed-downstream", log.Fields{"error": err, "meterID": DsMeterID, "deviceId": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000615 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400616 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530617 }
Gamze Abakafee36392019-10-03 11:17:24 +0000618
619 allocID := techProfileInstance.UsScheduler.AllocID
Gamze Abakafee36392019-10-03 11:17:24 +0000620 for _, gem := range techProfileInstance.UpstreamGemPortAttributeList {
Gamze Abakafee36392019-10-03 11:17:24 +0000621 gemPortIDs = append(gemPortIDs, gem.GemportID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400622 }
Gamze Abakafee36392019-10-03 11:17:24 +0000623
Girish Gowdra3d633032019-12-10 16:37:05 +0530624 if tpInstanceExists {
625 return allocID, gemPortIDs, techProfileInstance
626 }
627
628 allocIDs = appendUnique(allocIDs, allocID)
629 for _, gemPortID := range gemPortIDs {
630 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
631 }
632
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700633 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 +0530634 // Send Tconts and GEM ports to KV store
npujarec5762e2020-01-01 14:08:48 +0530635 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000636 return allocID, gemPortIDs, techProfileInstance
manikkaraj kbf256be2019-03-25 00:13:48 +0530637}
638
npujarec5762e2020-01-01 14:08:48 +0530639func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530640
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700641 logger.Debugw("storing-allocated-Tconts-and-GEM-ports-into-KV-store",
642 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "allocID": allocID, "gemPortIDs": gemPortIDs, "deviceId": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530643 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530644 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000645 logger.Error("Errow while uploading allocID to KV store")
manikkaraj kbf256be2019-03-25 00:13:48 +0530646 }
npujarec5762e2020-01-01 14:08:48 +0530647 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000648 logger.Error("Errow while uploading GEMports to KV store")
manikkaraj kbf256be2019-03-25 00:13:48 +0530649 }
npujarec5762e2020-01-01 14:08:48 +0530650 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000651 logger.Error("Errow while uploading gemtopon map to KV store")
manikkaraj kbf256be2019-03-25 00:13:48 +0530652 }
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700653 logger.Debugw("stored-tconts-and-GEM-into-KV-store-successfully", log.Fields{"deviceId": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400654 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530655 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400656 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530657}
658
659func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000660 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530661 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000662 for _, intfID := range techRange.IntfIds {
663 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400664 tpCount++
Girish Kumar2ad402b2020-03-20 19:45:12 +0000665 logger.Debugw("Init tech profile done", log.Fields{"intfID": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530666 }
667 }
668 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400669 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530670 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800671 "reason": "TP count does not match number of PON ports",
672 "tech-profile-count": tpCount,
Girish Kumarf26e4882020-03-05 06:49:10 +0000673 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts()}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530674 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000675 logger.Infow("Populated techprofile for ponports successfully",
Manikkaraj kb1d51442019-07-23 10:41:02 -0400676 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
manikkaraj kbf256be2019-03-25 00:13:48 +0530677 return nil
678}
679
npujarec5762e2020-01-01 14:08:48 +0530680func (f *OpenOltFlowMgr) addUpstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530681 portNo uint32, uplinkClassifier map[string]interface{},
682 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000683 allocID uint32, gemportID uint32, tpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700684 uplinkClassifier[PacketTagType] = SingleTag
Girish Kumar2ad402b2020-03-20 19:45:12 +0000685 logger.Debugw("Adding upstream data flow", log.Fields{"uplinkClassifier": uplinkClassifier, "uplinkAction": uplinkAction})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800686 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000687 Upstream, logicalFlow, allocID, gemportID, tpID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530688 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530689}
690
npujarec5762e2020-01-01 14:08:48 +0530691func (f *OpenOltFlowMgr) addDownstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530692 portNo uint32, downlinkClassifier map[string]interface{},
693 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000694 allocID uint32, gemportID uint32, tpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700695 downlinkClassifier[PacketTagType] = DoubleTag
Girish Kumar2ad402b2020-03-20 19:45:12 +0000696 logger.Debugw("Adding downstream data flow", log.Fields{"downlinkClassifier": downlinkClassifier,
Manikkaraj k884c1242019-04-11 16:26:42 +0530697 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400698 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
699 if vlan, exists := downlinkClassifier[VlanVid]; exists {
700 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700701 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Manikkaraj kb1d51442019-07-23 10:41:02 -0400702 if uint32(metadata.(uint64)) == MkUniPortNum(intfID, onuID, uniID) {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000703 logger.Infow("Ignoring DL trap device flow from core", log.Fields{"flow": logicalFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800704 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400705 }
706 }
707 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530708 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400709
Manikkaraj k884c1242019-04-11 16:26:42 +0530710 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700711 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400712 // vlan_vid is a uint32. must be type asserted as such or conversion fails
713 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530714 if ok {
715 downlinkAction[VlanVid] = dlClVid & 0xfff
716 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530717 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800718 "reason": "failed to convert VLANID classifier",
719 "vlan-id": VlanVid}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530720 }
721
David K. Bainbridge794735f2020-02-11 21:01:37 -0800722 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000723 Downstream, logicalFlow, allocID, gemportID, tpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530724}
725
npujarec5762e2020-01-01 14:08:48 +0530726func (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 +0530727 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000728 allocID uint32, gemPortID uint32, tpID uint32) error {
Manikkaraj k884c1242019-04-11 16:26:42 +0530729 /* One of the OLT platform (Broadcom BAL) requires that symmetric
730 flows require the same flow_id to be used across UL and DL.
731 Since HSIA flow is the only symmetric flow currently, we need to
732 re-use the flow_id across both direction. The 'flow_category'
733 takes priority over flow_cookie to find any available HSIA_FLOW
734 id for the ONU.
735 */
Girish Kumar2ad402b2020-03-20 19:45:12 +0000736 logger.Debugw("Adding HSIA flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "classifier": classifier,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700737 "action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530738 "logicalFlow": *logicalFlow})
Girish Gowdrafae935c2020-02-17 19:21:44 +0530739 var vlanPbit uint32 = 0xff // means no pbit
Gamze Abaka724d0852020-03-18 12:10:24 +0000740 var vlanVid uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400741 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000742 vlanPbit = classifier[VlanPcp].(uint32)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000743 logger.Debugw("Found pbit in the flow", log.Fields{"VlanPbit": vlanPbit})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800744 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000745 logger.Debugw("pbit-not-found-in-flow", log.Fields{"vlan-pcp": VlanPcp})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400746 }
Gamze Abaka724d0852020-03-18 12:10:24 +0000747 if _, ok := classifier[VlanVid]; ok {
748 vlanVid = classifier[VlanVid].(uint32)
749 log.Debugw("Found vlan in the flow", log.Fields{"VlanVid": vlanVid})
750 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700751 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530752 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000753 logger.Debug("flow-already-exists")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800754 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530755 }
Gamze Abaka724d0852020-03-18 12:10:24 +0000756 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanVid, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530757 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530758 return olterrors.NewErrNotFound("hsia-flow-id", log.Fields{"direction": direction}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530759 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800760 classifierProto, err := makeOpenOltClassifierField(classifier)
761 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530762 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530763 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000764 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +0000765 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800766 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530767 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530768 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000769 logger.Debugw("Created action proto", log.Fields{"action": *actionProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800770 networkIntfID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530771 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530772 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800773 log.Fields{
774 "classifier": classifier,
775 "action": action,
776 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530777 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700778 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
779 OnuId: int32(onuID),
780 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000781 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530782 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700783 AllocId: int32(allocID),
784 NetworkIntfId: int32(networkIntfID),
785 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530786 Classifier: classifierProto,
787 Action: actionProto,
788 Priority: int32(logicalFlow.Priority),
789 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000790 PortNo: portNo,
791 TechProfileId: tpID,
792 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800793 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530794 return olterrors.NewErrFlowOp("add", flowID, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530795 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000796 logger.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800797 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
798 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
799 flow.OnuId,
800 flow.UniId,
801 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530802 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": flow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800803 }
804 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +0530805}
Esin Karamanae41e2b2019-12-17 18:13:13 +0000806
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000807func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
808 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
809 gemPortID uint32, tpID uint32) error {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530810
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530811 networkIntfID, err := getNniIntfID(classifier, action)
812 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530813 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800814 "classifier": classifier,
815 "action": action},
816 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530817 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530818
819 // Clear the action map
820 for k := range action {
821 delete(action, k)
822 }
823
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700824 action[TrapToHost] = true
825 classifier[UDPSrc] = uint32(68)
826 classifier[UDPDst] = uint32(67)
827 classifier[PacketTagType] = SingleTag
828 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530829
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700830 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530831 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000832 logger.Debug("Flow-exists--not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800833 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530834 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530835
David K. Bainbridge794735f2020-02-11 21:01:37 -0800836 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 +0530837
838 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530839 return olterrors.NewErrNotFound("flow", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800840 "interface-id": intfID,
841 "gem-port": gemPortID,
842 "cookie": flowStoreCookie},
843 err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530844 }
845
Girish Kumar2ad402b2020-03-20 19:45:12 +0000846 logger.Debugw("Creating UL DHCP flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530847
David K. Bainbridge794735f2020-02-11 21:01:37 -0800848 classifierProto, err := makeOpenOltClassifierField(classifier)
849 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530850 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530851 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000852 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +0000853 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800854 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530855 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530856 }
857
David K. Bainbridge794735f2020-02-11 21:01:37 -0800858 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700859 OnuId: int32(onuID),
860 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530861 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700862 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700863 AllocId: int32(allocID),
864 NetworkIntfId: int32(networkIntfID),
865 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530866 Classifier: classifierProto,
867 Action: actionProto,
868 Priority: int32(logicalFlow.Priority),
869 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000870 PortNo: portNo,
871 TechProfileId: tpID,
872 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800873 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530874 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800875 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000876 logger.Debug("DHCP UL flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800877 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
878 if err := f.updateFlowInfoToKVStore(ctx, dhcpFlow.AccessIntfId,
879 dhcpFlow.OnuId,
880 dhcpFlow.UniId,
881 dhcpFlow.FlowId, flowsToKVStore); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530882 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId, log.Fields{"flow": dhcpFlow}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530883 }
884
David K. Bainbridge794735f2020-02-11 21:01:37 -0800885 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530886}
887
Esin Karamanae41e2b2019-12-17 18:13:13 +0000888//addIGMPTrapFlow creates IGMP trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +0530889func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000890 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, tpID uint32) error {
891 return f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, IgmpFlow, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +0000892}
893
894//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +0530895func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000896 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, flowType string, tpID uint32) error {
Esin Karamanae41e2b2019-12-17 18:13:13 +0000897
898 networkIntfID, err := getNniIntfID(classifier, action)
899 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530900 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800901 "classifier": classifier,
902 "action": action},
903 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000904 }
905
906 // Clear the action map
907 for k := range action {
908 delete(action, k)
909 }
910
911 action[TrapToHost] = true
912 classifier[PacketTagType] = SingleTag
913 delete(classifier, VlanVid)
914
915 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530916 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkIntfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000917 logger.Debug("Flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800918 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +0000919 }
920
npujarec5762e2020-01-01 14:08:48 +0530921 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 +0000922
923 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530924 return olterrors.NewErrNotFound("flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800925 "interface-id": intfID,
926 "oni-id": onuID,
927 "cookie": flowStoreCookie,
928 "flow-type": flowType},
929 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000930 }
931
Girish Kumar2ad402b2020-03-20 19:45:12 +0000932 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 +0000933
David K. Bainbridge794735f2020-02-11 21:01:37 -0800934 classifierProto, err := makeOpenOltClassifierField(classifier)
935 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530936 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000937 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000938 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +0000939 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800940 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530941 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000942 }
943
David K. Bainbridge794735f2020-02-11 21:01:37 -0800944 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +0000945 OnuId: int32(onuID),
946 UniId: int32(uniID),
947 FlowId: flowID,
948 FlowType: Upstream,
949 AllocId: int32(allocID),
950 NetworkIntfId: int32(networkIntfID),
951 GemportId: int32(gemPortID),
952 Classifier: classifierProto,
953 Action: actionProto,
954 Priority: int32(logicalFlow.Priority),
955 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000956 PortNo: portNo,
957 TechProfileId: tpID,
958 }
Esin Karamanae41e2b2019-12-17 18:13:13 +0000959
David K. Bainbridge794735f2020-02-11 21:01:37 -0800960 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530961 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": flow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800962 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000963 logger.Debugf("%s UL flow added to device successfully", flowType)
Esin Karamanae41e2b2019-12-17 18:13:13 +0000964
David K. Bainbridge794735f2020-02-11 21:01:37 -0800965 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, flowType, flowID, logicalFlow.Id)
966 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
967 flow.OnuId,
968 flow.UniId,
969 flow.FlowId, flowsToKVStore); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530970 return olterrors.NewErrPersistence("update", "flow", flow.FlowId, log.Fields{"flow": flow}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000971 }
972
David K. Bainbridge794735f2020-02-11 21:01:37 -0800973 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +0000974}
975
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700976// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000977func (f *OpenOltFlowMgr) addEAPOLFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
978 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
979 gemPortID uint32, vlanID uint32, tpID uint32) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000980 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 +0530981
982 uplinkClassifier := make(map[string]interface{})
983 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +0530984
manikkaraj kbf256be2019-03-25 00:13:48 +0530985 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700986 uplinkClassifier[EthType] = uint32(EapEthType)
987 uplinkClassifier[PacketTagType] = SingleTag
988 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +0000989 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +0530990 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700991 uplinkAction[TrapToHost] = true
992 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530993 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000994 logger.Debug("Flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800995 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530996 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530997 //Add Uplink EAPOL Flow
Gamze Abaka724d0852020-03-18 12:10:24 +0000998 uplinkFlowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0, 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530999 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301000 return olterrors.NewErrNotFound("flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001001 "interface-id": intfID,
1002 "onu-id": onuID,
1003 "coookie": flowStoreCookie},
1004 err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301005 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001006 logger.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301007
David K. Bainbridge794735f2020-02-11 21:01:37 -08001008 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1009 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301010 return olterrors.NewErrInvalidValue(log.Fields{"classifier": uplinkClassifier}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301011 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001012 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001013 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001014 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301015 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301016 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001017 logger.Debugw("Created action proto", log.Fields{"action": *actionProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001018 networkIntfID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301019 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301020 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001021 "classifier": classifier,
1022 "action": action},
1023 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301024 }
1025
David K. Bainbridge794735f2020-02-11 21:01:37 -08001026 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001027 OnuId: int32(onuID),
1028 UniId: int32(uniID),
1029 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001030 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001031 AllocId: int32(allocID),
1032 NetworkIntfId: int32(networkIntfID),
1033 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301034 Classifier: classifierProto,
1035 Action: actionProto,
1036 Priority: int32(logicalFlow.Priority),
1037 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001038 PortNo: portNo,
1039 TechProfileId: tpID,
1040 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001041 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301042 return olterrors.NewErrFlowOp("add", uplinkFlowID, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001043 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001044 logger.Debug("EAPOL UL flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001045 flowCategory := "EAPOL"
1046 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
1047 if err := f.updateFlowInfoToKVStore(ctx, upstreamFlow.AccessIntfId,
1048 upstreamFlow.OnuId,
1049 upstreamFlow.UniId,
1050 upstreamFlow.FlowId,
1051 /* lowCategory, */
1052 flowsToKVStore); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301053 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId, log.Fields{"flow": upstreamFlow}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301054 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301055
Girish Kumar2ad402b2020-03-20 19:45:12 +00001056 logger.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001057 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301058}
1059
David K. Bainbridge794735f2020-02-11 21:01:37 -08001060func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001061 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001062
1063 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1064 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1065 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001066 if vlanID != ReservedVlan {
1067 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001068 classifier.OVid = vid
1069 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301070 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001071 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1072 vid := uint32(metadata)
1073 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001074 classifier.IVid = vid
1075 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301076 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301077 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001078 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301079 classifier.OPbits = vlanPcp
1080 } else {
1081 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301082 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001083 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1084 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1085 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1086 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001087 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001088 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1089 classifier.PktTagType = pktTagType
1090
1091 switch pktTagType {
1092 case SingleTag:
1093 case DoubleTag:
1094 case Untagged:
1095 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001096 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301097 }
1098 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001099 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301100}
1101
Gamze Abaka724d0852020-03-18 12:10:24 +00001102func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001103 var actionCmd openoltpb2.ActionCmd
1104 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301105 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001106 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301107 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001108 if _, ok := actionInfo[VlanPcp]; ok {
1109 action.Cmd.RemarkInnerPbits = true
1110 action.IPbits = actionInfo[VlanPcp].(uint32)
1111 if _, ok := actionInfo[VlanVid]; ok {
1112 action.Cmd.TranslateInnerTag = true
1113 action.IVid = actionInfo[VlanVid].(uint32)
1114 }
1115 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001116 } else if _, ok := actionInfo[PushVlan]; ok {
1117 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301118 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001119 if _, ok := actionInfo[VlanPcp]; ok {
1120 action.OPbits = actionInfo[VlanPcp].(uint32)
1121 action.Cmd.RemarkOuterPbits = true
1122 if _, ok := classifierInfo[VlanVid]; ok {
1123 action.IVid = classifierInfo[VlanVid].(uint32)
1124 action.Cmd.TranslateInnerTag = true
1125 }
1126 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001127 } else if _, ok := actionInfo[TrapToHost]; ok {
1128 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301129 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001130 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301131 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001132 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301133}
1134
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001135// getTPpath return the ETCD path for a given UNI port
1136func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uniPath string, TpID uint32) string {
1137 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301138}
1139
Gamze Abakafee36392019-10-03 11:17:24 +00001140// DeleteTechProfileInstances removes the tech profile instances from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301141func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, sn string) error {
1142 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001143 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1144
Gamze Abakafee36392019-10-03 11:17:24 +00001145 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301146 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001147 olterrors.NewErrAdapter("delete-tech-profile-failed", nil, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301148 // return err
1149 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001150 }
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001151 log.Debugw("tech-profile-deleted", log.Fields{"deviceId": f.deviceHandler.device.Id, "tp": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001152 }
1153 return nil
1154}
1155
1156// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301157func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001158 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001159 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001160 }
npujarec5762e2020-01-01 14:08:48 +05301161 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001162 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 -04001163 }
1164 return nil
1165}
1166
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001167func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +05301168 if len(classifier) == 0 { // should never happen
Girish Kumar2ad402b2020-03-20 19:45:12 +00001169 logger.Error("Invalid classfier object")
manikkaraj kbf256be2019-03-25 00:13:48 +05301170 return 0
1171 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001172 logger.Debugw("generating flow store cookie", log.Fields{"classifier": classifier, "gemPortID": gemPortID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301173 var jsonData []byte
1174 var flowString string
1175 var err error
1176 // TODO: Do we need to marshall ??
1177 if jsonData, err = json.Marshal(classifier); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001178 logger.Error("Failed to encode classifier")
manikkaraj kbf256be2019-03-25 00:13:48 +05301179 return 0
1180 }
1181 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001182 if gemPortID != 0 {
1183 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +05301184 }
1185 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001186 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +05301187 hash := big.NewInt(0)
1188 hash.SetBytes(h.Sum(nil))
Girish Gowdra3d633032019-12-10 16:37:05 +05301189 generatedHash := hash.Uint64()
Girish Kumar2ad402b2020-03-20 19:45:12 +00001190 logger.Debugw("hash generated", log.Fields{"hash": generatedHash})
Girish Gowdra3d633032019-12-10 16:37:05 +05301191 return generatedHash
manikkaraj kbf256be2019-03-25 00:13:48 +05301192}
1193
npujarec5762e2020-01-01 14:08:48 +05301194func (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 +05301195 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001196 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001197 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1198 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1199 */
1200 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001201 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001202 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001203 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001204 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001205 // Get existing flows matching flowid for given subscriber from KV store
npujarec5762e2020-01-01 14:08:48 +05301206 existingFlows := f.resourceMgr.GetFlowIDInfo(ctx, intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001207 if existingFlows != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001208 logger.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001209 //for _, f := range *existingFlows {
1210 // flows = append(flows, f)
1211 //}
1212 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001213 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001214 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 +05301215 return &flows
1216}
1217
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001218//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
1219// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
1220// var intfId uint32
1221// /* For flows which trap out of the NNI, the AccessIntfId is invalid
1222// (set to -1). In such cases, we need to refer to the NetworkIntfId .
1223// */
1224// if flow.AccessIntfId != -1 {
1225// intfId = uint32(flow.AccessIntfId)
1226// } else {
1227// intfId = uint32(flow.NetworkIntfId)
1228// }
1229// // Get existing flows matching flowid for given subscriber from KV store
1230// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
1231// if existingFlows != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001232// logger.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001233// for _, f := range *existingFlows {
1234// flows = append(flows, f)
1235// }
1236// }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001237// 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 -04001238// return &flows
1239//}
1240
npujarec5762e2020-01-01 14:08:48 +05301241func (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 +00001242 logger.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
npujarec5762e2020-01-01 14:08:48 +05301243 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, intfID, onuID, uniID, flowID, flows); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001244 logger.Debug("Error while Storing flow into KV store")
manikkaraj k17652a72019-05-06 09:06:36 -04001245 return err
1246 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001247 logger.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +05301248 return nil
1249}
1250
David K. Bainbridge794735f2020-02-11 21:01:37 -08001251func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001252
1253 var intfID uint32
1254 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1255 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1256 */
1257 if deviceFlow.AccessIntfId != -1 {
1258 intfID = uint32(deviceFlow.AccessIntfId)
1259 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001260 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001261 intfID = uint32(deviceFlow.NetworkIntfId)
1262 }
1263
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001264 logger.Debugw("sending-flow-to-device-via-grpc", log.Fields{
1265 "flow": *deviceFlow,
1266 "deviceId": f.deviceHandler.device.Id,
1267 })
manikkaraj kbf256be2019-03-25 00:13:48 +05301268 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001269
1270 st, _ := status.FromError(err)
1271 if st.Code() == codes.AlreadyExists {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001272 logger.Debug("flow-already-exists", log.Fields{
1273 "err": err,
1274 "deviceFlow": deviceFlow,
1275 "deviceId": f.deviceHandler.device.Id,
1276 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001277 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301278 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001279
1280 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001281 logger.Errorw("failed-to-Add-flow-to-device", log.Fields{
1282 "err": err,
1283 "deviceFlow": deviceFlow,
1284 "deviceId": f.deviceHandler.device.Id,
1285 })
npujarec5762e2020-01-01 14:08:48 +05301286 f.resourceMgr.FreeFlowID(ctx, intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001287 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001288 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301289 if deviceFlow.GemportId != -1 {
1290 // No need to register the flow if it is a trap on nni flow.
npujarec5762e2020-01-01 14:08:48 +05301291 f.registerFlow(ctx, logicalFlow, deviceFlow)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301292 }
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001293 logger.Debugw("flow-added-to-device-successfully", log.Fields{
1294 "flow": *deviceFlow,
1295 "deviceId": f.deviceHandler.device.Id,
1296 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001297 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001298}
1299
David K. Bainbridge794735f2020-02-11 21:01:37 -08001300func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001301 logger.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001302 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1303 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001304 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001305 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 -07001306 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001307 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001308 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001309 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001310
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001311 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001312 logger.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001313 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301314}
1315
1316/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1317 //update core flows_proxy : flows_proxy.update('/', flows)
1318}
1319
1320func generateStoredId(flowId uint32, direction string)uint32{
1321
David K. Bainbridge82efc492019-09-04 09:57:11 -07001322 if direction == Upstream{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001323 logger.Debug("Upstream flow shifting flowid")
manikkaraj kbf256be2019-03-25 00:13:48 +05301324 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001325 }else if direction == Downstream{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001326 logger.Debug("Downstream flow not shifting flowid")
manikkaraj kbf256be2019-03-25 00:13:48 +05301327 return flowId
1328 }else{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001329 logger.Errorw("Unrecognized direction",log.Fields{"direction": direction})
manikkaraj kbf256be2019-03-25 00:13:48 +05301330 return flowId
1331 }
1332}
1333
1334*/
1335
David K. Bainbridge794735f2020-02-11 21:01:37 -08001336func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001337
1338 classifierInfo := make(map[string]interface{})
1339 actionInfo := make(map[string]interface{})
1340
1341 classifierInfo[EthType] = uint32(LldpEthType)
1342 classifierInfo[PacketTagType] = Untagged
1343 actionInfo[TrapToHost] = true
1344
1345 // LLDP flow is installed to trap LLDP packets on the NNI port.
1346 // We manage flow_id resource pool on per PON port basis.
1347 // Since this situation is tricky, as a hack, we pass the NNI port
1348 // index (network_intf_id) as PON port Index for the flow_id resource
1349 // pool. Also, there is no ONU Id available for trapping LLDP packets
1350 // on NNI port, use onu_id as -1 (invalid)
1351 // ****************** CAVEAT *******************
1352 // This logic works if the NNI Port Id falls within the same valid
1353 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1354 // we need to have a re-look at this.
1355 // *********************************************
1356
1357 var onuID = -1
1358 var uniID = -1
1359 var gemPortID = -1
1360
David K. Bainbridge794735f2020-02-11 21:01:37 -08001361 networkInterfaceID, err := IntfIDFromNniPortNum(portNo)
1362 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301363 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001364 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001365 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05301366 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001367 logger.Debug("Flow-exists--not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001368 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001369 }
npujarec5762e2020-01-01 14:08:48 +05301370 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001371
1372 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301373 return olterrors.NewErrNotFound("flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001374 "interface-id": networkInterfaceID,
1375 "onu-id": onuID,
1376 "uni-id": uniID,
1377 "gem-port-id": gemPortID,
1378 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00001379 err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001380 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001381 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1382 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001383 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001384 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001385 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001386 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001387 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001388 return olterrors.NewErrInvalidValue(log.Fields{"action": actionInfo}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001389 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001390 logger.Debugw("Created action proto", log.Fields{"action": *actionProto})
Humera Kouser94d7a842019-08-25 19:04:32 -04001391
1392 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1393 OnuId: int32(onuID), // OnuId not required
1394 UniId: int32(uniID), // UniId not used
1395 FlowId: flowID,
1396 FlowType: Downstream,
1397 NetworkIntfId: int32(networkInterfaceID),
1398 GemportId: int32(gemPortID),
1399 Classifier: classifierProto,
1400 Action: actionProto,
1401 Priority: int32(flow.Priority),
1402 Cookie: flow.Cookie,
1403 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001404 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001405 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001406 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001407 logger.Debug("LLDP trap on NNI flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001408 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, flow.Id)
1409 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
1410 int32(onuID),
1411 int32(uniID),
1412 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001413 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001414 }
1415 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301416}
1417
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001418func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1419 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001420}
1421
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001422//getOnuDevice to fetch onu from cache or core.
1423func (f *OpenOltFlowMgr) getOnuDevice(intfID uint32, onuID uint32) (*OnuDevice, error) {
1424 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1425 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1426 if !ok {
1427 logger.Debugw("couldnt-find-onu-in-cache", log.Fields{"intfID": intfID, "onuID": onuID})
1428 onuDevice, err := f.getChildDevice(intfID, onuID)
1429 if err != nil {
1430 return nil, olterrors.NewErrNotFound("onu-child-device", log.Fields{"onuId": onuID, "intfID": intfID}, err)
1431 }
1432 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1433 //better to ad the device to cache here.
1434 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1435 } else {
1436 logger.Debugw("Found-onu-in-cache", log.Fields{"intfID": intfID, "onuID": onuID})
1437 }
1438
1439 return onuDev.(*OnuDevice), nil
1440}
1441
1442//getChildDevice to fetch onu
1443func (f *OpenOltFlowMgr) getChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001444 logger.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001445 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001446 onuDevice, err := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
1447 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301448 return nil, olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001449 "interface-id": parentPortNo,
1450 "onu-id": onuID},
Girish Kumarf26e4882020-03-05 06:49:10 +00001451 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301452 }
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001453 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 +05301454 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301455}
1456
1457func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001458 logger.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301459 return nil
1460}
1461
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001462func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001463 logger.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301464}
1465
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001466func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001467 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001468 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001469 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001470 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001471}
1472
Girish Gowdra6b130582019-11-20 16:45:20 +05301473func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001474 onuDev, err := f.getOnuDevice(intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301475 if err != nil {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001476 logger.Debugw("couldnt-find-onu-child-device", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1477 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301478 }
1479
1480 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001481 logger.Debugw("sending gem port delete to openonu adapter", log.Fields{"msg": *delGemPortMsg})
Girish Gowdra6b130582019-11-20 16:45:20 +05301482 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1483 delGemPortMsg,
1484 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
1485 f.deviceHandler.deviceType,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001486 onuDev.deviceType,
1487 onuDev.deviceID,
1488 onuDev.proxyDeviceID, ""); sendErr != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001489 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001490 "toAdapter": onuDev.deviceType, "onuId": onuDev.deviceID,
1491 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301492 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001493 logger.Debugw("success sending del gem port to onu adapter", log.Fields{"msg": delGemPortMsg})
Girish Gowdra6b130582019-11-20 16:45:20 +05301494 return nil
1495}
1496
1497func (f *OpenOltFlowMgr) sendDeleteTcontToChild(intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001498 onuDev, err := f.getOnuDevice(intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301499 if err != nil {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001500 logger.Debugw("couldnt-find-onu-child-device", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1501 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301502 }
1503
1504 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001505 logger.Debugw("sending tcont delete to openonu adapter", log.Fields{"msg": *delTcontMsg})
Girish Gowdra6b130582019-11-20 16:45:20 +05301506 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1507 delTcontMsg,
1508 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
1509 f.deviceHandler.deviceType,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001510 onuDev.deviceType,
1511 onuDev.deviceID,
1512 onuDev.proxyDeviceID, ""); sendErr != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001513 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001514 "toAdapter": onuDev.deviceType, "onuId": onuDev.deviceID,
1515 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301516 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001517 logger.Debugw("success sending del tcont to onu adapter", log.Fields{"msg": delTcontMsg})
Girish Gowdra6b130582019-11-20 16:45:20 +05301518 return nil
1519}
1520
Girish Gowdra3d633032019-12-10 16:37:05 +05301521func (f *OpenOltFlowMgr) deletePendingFlows(Intf uint32, onuID int32, uniID int32) {
1522 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1523 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); ok {
1524 if val.(int) > 0 {
1525 pnFlDels := val.(int) - 1
1526 if pnFlDels > 0 {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001527 logger.Debugw("flow delete succeeded, more pending",
Girish Gowdra3d633032019-12-10 16:37:05 +05301528 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID, "currPendingFlowCnt": pnFlDels})
1529 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1530 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001531 logger.Debugw("all pending flow deletes handled, removing entry from map",
Girish Gowdra3d633032019-12-10 16:37:05 +05301532 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1533 f.pendingFlowDelete.Delete(pnFlDelKey)
1534 }
1535 }
1536 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001537 logger.Debugw("no pending delete flows found",
Girish Gowdra3d633032019-12-10 16:37:05 +05301538 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1539
1540 }
1541
1542}
1543
Girish Gowdrac3037402020-01-22 20:29:53 +05301544// Once the gemport is released for a given onu, it also has to be cleared from local cache
1545// which was used for deriving the gemport->logicalPortNo during packet-in.
1546// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1547// is conveyed to ONOS during packet-in OF message.
1548func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(intfID uint32, onuID uint32, gemPortID uint32) {
1549 f.lockCache.Lock()
1550 defer f.lockCache.Unlock()
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001551 logger.Debugw("deleting-gem-from-local-cache",
1552 log.Fields{"gem": gemPortID, "intf": intfID, "onu": onuID, "deviceId": f.deviceHandler.device.Id, "onuGem": f.onuGemInfo[intfID]})
Girish Gowdrac3037402020-01-22 20:29:53 +05301553 onugem := f.onuGemInfo[intfID]
serkant.uluderya96af4932020-02-20 16:58:48 -08001554 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301555 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001556 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301557 // If the gemport is found, delete it from local cache.
1558 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001559 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1560 onugem[i] = onu
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001561 logger.Debugw("removed-gemport-from-local-cache",
1562 log.Fields{"intfID": intfID, "onuID": onuID, "deletedGemPortID": gemPortID, "gemPorts": onu.GemPorts, "deviceId": f.deviceHandler.device.Id})
Girish Gowdrac3037402020-01-22 20:29:53 +05301563 break
1564 }
1565 }
1566 break
1567 }
1568 }
1569}
1570
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301571//clearResources clears pon resources in kv store and the device
npujarec5762e2020-01-01 14:08:48 +05301572func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301573 gemPortID int32, flowID uint32, flowDirection string,
1574 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001575
Chaitrashree G S90a17952019-11-14 21:51:21 -05001576 tpID, err := getTpIDFromFlow(flow)
1577 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001578 return olterrors.NewErrNotFound("tpid", log.Fields{"flow": flow, "pon": Intf, "onuID": onuID, "uniID": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001579 }
Gamze Abakafee36392019-10-03 11:17:24 +00001580
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001581 if len(updatedFlows) >= 0 {
1582 // There are still flows referencing the same flow_id.
1583 // So the flow should not be freed yet.
1584 // For ex: Case of HSIA where same flow is shared
1585 // between DS and US.
Girish Kumarf26e4882020-03-05 06:49:10 +00001586 if err := f.updateFlowInfoToKVStore(ctx, int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows); err != nil {
1587 olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": updatedFlows}, err).Log()
1588 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001589 if len(updatedFlows) == 0 {
Girish Gowdra3d633032019-12-10 16:37:05 +05301590 // Do this for subscriber flows only (not trap from NNI flows)
1591 if onuID != -1 && uniID != -1 {
1592 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1593 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001594 logger.Debugw("creating entry for pending flow delete",
Girish Gowdra3d633032019-12-10 16:37:05 +05301595 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1596 f.pendingFlowDelete.Store(pnFlDelKey, 1)
1597 } else {
1598 pnFlDels := val.(int) + 1
Girish Kumar2ad402b2020-03-20 19:45:12 +00001599 logger.Debugw("updating flow delete entry",
Girish Gowdra3d633032019-12-10 16:37:05 +05301600 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID, "currPendingFlowCnt": pnFlDels})
1601 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1602 }
1603
1604 defer f.deletePendingFlows(Intf, onuID, uniID)
1605 }
1606
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001607 logger.Debugw("releasing-flow-id-to-resource-manager", log.Fields{
1608 "Intf": Intf, "onuId": onuID, "uniId": uniID, "flowId": flowID,
1609 "deviceId": f.deviceHandler.device.Id,
1610 })
npujarec5762e2020-01-01 14:08:48 +05301611 f.resourceMgr.FreeFlowID(ctx, Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001612
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001613 uni := getUniPortPath(f.deviceHandler.device.Id, Intf, onuID, uniID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301614 tpPath := f.getTPpath(Intf, uni, tpID)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001615 logger.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
npujarec5762e2020-01-01 14:08:48 +05301616 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
Girish Kumarf26e4882020-03-05 06:49:10 +00001617 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1618 return olterrors.NewErrNotFound("tech-profile-in-kv-store", log.Fields{"tpID": tpID, "path": tpPath}, err)
Gamze Abakafee36392019-10-03 11:17:24 +00001619 }
1620
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301621 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00001622 if f.isGemPortUsedByAnotherFlow(gemPK) {
1623 flowIDs := f.flowsUsedByGemPort[gemPK]
1624 for i, flowIDinMap := range flowIDs {
1625 if flowIDinMap == flowID {
1626 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301627 // everytime flowsUsedByGemPort cache is updated the same should be updated
1628 // in kv store by calling UpdateFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001629 f.flowsUsedByGemPort[gemPK] = flowIDs
npujarec5762e2020-01-01 14:08:48 +05301630 f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs)
Gamze Abakafee36392019-10-03 11:17:24 +00001631 break
1632 }
1633 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001634 logger.Debugw("Gem port id is still used by other flows", log.Fields{"gemPortID": gemPortID, "usedByFlows": flowIDs})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301635 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00001636 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001637 logger.Debugf("Gem port id %d is not used by another flow - releasing the gem port", gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301638 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001639 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1640 // 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 +05301641 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
Girish Gowdrac3037402020-01-22 20:29:53 +05301642 f.deleteGemPortFromLocalCache(Intf, uint32(onuID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001643 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301644 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1645 // by calling DeleteFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001646 delete(f.flowsUsedByGemPort, gemPK)
npujarec5762e2020-01-01 14:08:48 +05301647 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
1648 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001649 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05301650 // Delete the gem port on the ONU.
1651 if err := f.sendDeleteGemPortToChild(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001652 logger.Errorw("error processing delete gem-port towards onu",
Girish Gowdra6b130582019-11-20 16:45:20 +05301653 log.Fields{"err": err, "pon": Intf, "onuID": onuID, "uniID": uniID, "gemPortId": gemPortID})
1654 }
Gamze Abakafee36392019-10-03 11:17:24 +00001655
npujarec5762e2020-01-01 14:08:48 +05301656 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001657 if !ok {
npujarec5762e2020-01-01 14:08:48 +05301658 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID)
1659 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1660 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1661 f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID)
1662 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301663 // Delete the TCONT on the ONU.
1664 if err := f.sendDeleteTcontToChild(Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001665 logger.Errorw("error processing delete tcont towards onu",
Girish Gowdra6b130582019-11-20 16:45:20 +05301666 log.Fields{"pon": Intf, "onuID": onuID, "uniID": uniID, "allocId": techprofileInst.UsScheduler.AllocID})
1667 }
Gamze Abakafee36392019-10-03 11:17:24 +00001668 }
1669 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001670 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301671 return nil
1672}
1673
David K. Bainbridge794735f2020-02-11 21:01:37 -08001674// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05301675func (f *OpenOltFlowMgr) clearFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) {
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301676
Girish Kumar2ad402b2020-03-20 19:45:12 +00001677 logger.Debugw("clearFlowFromResourceManager", log.Fields{"flowDirection": flowDirection, "flow": *flow})
Esin Karamanccb714b2019-11-29 15:02:06 +00001678
1679 if flowDirection == Multicast {
npujarec5762e2020-01-01 14:08:48 +05301680 f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00001681 return
1682 }
1683
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301684 var updatedFlows []rsrcMgr.FlowInfo
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301685 classifierInfo := make(map[string]interface{})
1686
1687 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
1688 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001689 logger.Error(err)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301690 return
1691 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301692
David K. Bainbridge794735f2020-02-11 21:01:37 -08001693 onuID := int32(onu)
1694 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301695
1696 for _, field := range flows.GetOfbFields(flow) {
1697 if field.Type == flows.IP_PROTO {
1698 classifierInfo[IPProto] = field.GetIpProto()
Girish Kumar2ad402b2020-03-20 19:45:12 +00001699 logger.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301700 }
1701 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001702 logger.Debugw("Extracted access info from flow to be deleted",
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301703 log.Fields{"ponIntf": Intf, "onuID": onuID, "uniID": uniID})
1704
1705 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1706 onuID = -1
1707 uniID = -1
Girish Kumar2ad402b2020-03-20 19:45:12 +00001708 logger.Debug("Trap on nni flow set oni, uni to -1")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001709 Intf, err = IntfIDFromNniPortNum(inPort)
1710 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001711 logger.Errorw("invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001712 log.Fields{
1713 "port-number": inPort,
1714 "error": err})
1715 return
1716 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301717 }
npujarec5762e2020-01-01 14:08:48 +05301718 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, Intf, onuID, uniID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001719 for _, flowID := range flowIds {
npujarec5762e2020-01-01 14:08:48 +05301720 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flowID)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301721 if flowInfo == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001722 logger.Debugw("No FlowInfo found found in KV store",
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301723 log.Fields{"Intf": Intf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1724 return
1725 }
1726 updatedFlows = nil
1727 for _, flow := range *flowInfo {
1728 updatedFlows = append(updatedFlows, flow)
1729 }
1730
1731 for i, storedFlow := range updatedFlows {
1732 if flow.Id == storedFlow.LogicalFlowID {
1733 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001734 logger.Debugw("Flow to be deleted", log.Fields{"flow": storedFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001735 // DKB
1736 if err = f.removeFlowFromDevice(&removeFlowMessage); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001737 logger.Errorw("failed-to-remove-flow", log.Fields{"error": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001738 return
1739 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001740 logger.Debug("Flow removed from device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001741 //Remove the Flow from FlowInfo
1742 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1743 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
1744 flowID, flowDirection, portNum, updatedFlows); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001745 logger.Error("Failed to clear resources for flow", log.Fields{"flow": storedFlow})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301746 return
1747 }
1748 }
1749 }
1750 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001751}
1752
Esin Karamanccb714b2019-11-29 15:02:06 +00001753//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
1754// clears resources reserved for this multicast flow
npujarec5762e2020-01-01 14:08:48 +05301755func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) {
Esin Karamanccb714b2019-11-29 15:02:06 +00001756 classifierInfo := make(map[string]interface{})
1757 formulateClassifierInfoFromFlow(classifierInfo, flow)
Esin Karaman65409d82020-03-18 10:58:18 +00001758 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00001759
1760 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001761 logger.Warnw("No inPort found. Cannot release resources of the multicast flow.", log.Fields{"flowId:": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001762 return
1763 }
1764
Esin Karamanccb714b2019-11-29 15:02:06 +00001765 var onuID = int32(NoneOnuID)
1766 var uniID = int32(NoneUniID)
1767 var flowID uint32
1768 var updatedFlows []rsrcMgr.FlowInfo
1769
npujarec5762e2020-01-01 14:08:48 +05301770 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, networkInterfaceID, onuID, uniID)
Esin Karamanccb714b2019-11-29 15:02:06 +00001771
1772 for _, flowID = range flowIds {
npujarec5762e2020-01-01 14:08:48 +05301773 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00001774 if flowInfo == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001775 logger.Debugw("No multicast FlowInfo found in the KV store",
Esin Karamanccb714b2019-11-29 15:02:06 +00001776 log.Fields{"Intf": networkInterfaceID, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1777 continue
1778 }
1779 updatedFlows = nil
1780 for _, flow := range *flowInfo {
1781 updatedFlows = append(updatedFlows, flow)
1782 }
1783 for i, storedFlow := range updatedFlows {
1784 if flow.Id == storedFlow.LogicalFlowID {
1785 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001786 logger.Debugw("Multicast flow to be deleted", log.Fields{"flow": storedFlow})
Esin Karamanccb714b2019-11-29 15:02:06 +00001787 //remove from device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001788 if err := f.removeFlowFromDevice(&removeFlowMessage); err != nil {
1789 // DKB
Girish Kumar2ad402b2020-03-20 19:45:12 +00001790 logger.Errorw("failed-to-remove-multicast-flow",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001791 log.Fields{
1792 "flow-id": flow.Id,
1793 "error": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00001794 return
1795 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001796 logger.Debugw("Multicast flow removed from device successfully", log.Fields{"flowId": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001797 //Remove the Flow from FlowInfo
1798 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
npujarec5762e2020-01-01 14:08:48 +05301799 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID), NoneOnuID, NoneUniID, flowID, &updatedFlows); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001800 logger.Error("Failed to delete multicast flow from the KV store", log.Fields{"flow": storedFlow, "err": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00001801 return
1802 }
1803 //release flow id
Girish Kumar2ad402b2020-03-20 19:45:12 +00001804 logger.Debugw("Releasing multicast flow id", log.Fields{"flowId": flowID, "interfaceID": networkInterfaceID})
npujarec5762e2020-01-01 14:08:48 +05301805 f.resourceMgr.FreeFlowID(ctx, uint32(networkInterfaceID), NoneOnuID, NoneUniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00001806 }
1807 }
1808 }
1809}
1810
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001811//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07001812func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001813 logger.Debugw("Removing Flow", log.Fields{"flow": flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301814 var direction string
1815 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001816
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301817 for _, action := range flows.GetActions(flow) {
1818 if action.Type == flows.OUTPUT {
1819 if out := action.GetOutput(); out != nil {
1820 actionInfo[Output] = out.GetPort()
Girish Kumar2ad402b2020-03-20 19:45:12 +00001821 logger.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301822 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001823 logger.Error("Invalid output port in action")
Girish Gowdracefae192020-03-19 18:14:10 -07001824 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001825 }
1826 }
1827 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001828
1829 if flows.HasGroup(flow) {
1830 direction = Multicast
Girish Gowdracefae192020-03-19 18:14:10 -07001831 f.clearFlowFromResourceManager(ctx, flow, direction)
1832 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00001833 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301834 direction = Upstream
1835 } else {
1836 direction = Downstream
1837 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301838
Girish Gowdracefae192020-03-19 18:14:10 -07001839 _, intfID, onuID, uniID, _, _, err := FlowExtractInfo(flow, direction)
1840 if err != nil {
1841 return err
1842 }
1843
1844 userKey := tpLockKey{intfID, onuID, uniID}
1845
1846 // Serialize flow removes on a per subscriber basis
1847 if f.perUserFlowHandleLock.TryLock(userKey) {
1848 f.clearFlowFromResourceManager(ctx, flow, direction) //TODO: Take care of the limitations
1849 f.perUserFlowHandleLock.Unlock(userKey)
1850 } else {
1851 // Ideally this should never happen
Girish Kumar2ad402b2020-03-20 19:45:12 +00001852 logger.Errorw("failed to acquire lock to remove flow, flow remove aborted", log.Fields{"flow": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001853 return errors.New("failed-to-acquire-per-user-lock")
1854 }
1855
1856 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001857}
1858
Girish Gowdra3d633032019-12-10 16:37:05 +05301859func (f *OpenOltFlowMgr) waitForFlowDeletesToCompleteForOnu(ctx context.Context, intfID uint32, onuID uint32,
1860 uniID uint32, ch chan bool) {
1861 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
1862 for {
1863 select {
1864 case <-time.After(20 * time.Millisecond):
1865 if flowDelRefCnt, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok || flowDelRefCnt == 0 {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001866 logger.Debug("pending flow deletes completed")
Girish Gowdra3d633032019-12-10 16:37:05 +05301867 ch <- true
1868 return
1869 }
1870 case <-ctx.Done():
Girish Kumar2ad402b2020-03-20 19:45:12 +00001871 logger.Error("flow delete wait handler routine canceled")
Girish Gowdra3d633032019-12-10 16:37:05 +05301872 return
1873 }
1874 }
1875}
1876
Esin Karamanae41e2b2019-12-17 18:13:13 +00001877//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
1878func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
1879 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
1880 if ethType, ok := classifierInfo[EthType]; ok {
1881 if ethType.(uint32) == IPv4EthType {
1882 if ipProto, ok := classifierInfo[IPProto]; ok {
1883 if ipProto.(uint32) == IgmpProto {
1884 return true
1885 }
1886 }
1887 }
1888 }
1889 }
1890 return false
1891}
1892
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001893// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05301894// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01001895func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001896 classifierInfo := make(map[string]interface{})
1897 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001898 var UsMeterID uint32
1899 var DsMeterID uint32
1900
Girish Kumar2ad402b2020-03-20 19:45:12 +00001901 logger.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001902 formulateClassifierInfoFromFlow(classifierInfo, flow)
1903
1904 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
1905 if err != nil {
1906 // Error logging is already done in the called function
1907 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001908 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301909 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001910
Esin Karamanccb714b2019-11-29 15:02:06 +00001911 if flows.HasGroup(flow) {
1912 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01001913 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00001914 }
1915
manikkaraj k17652a72019-05-06 09:06:36 -04001916 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00001917 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
1918 if err != nil {
1919 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01001920 return err
manikkaraj k17652a72019-05-06 09:06:36 -04001921 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001922
Girish Kumar2ad402b2020-03-20 19:45:12 +00001923 logger.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001924 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00001925
Humera Kouser94d7a842019-08-25 19:04:32 -04001926 if ethType, ok := classifierInfo[EthType]; ok {
1927 if ethType.(uint32) == LldpEthType {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001928 logger.Info("Adding LLDP flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01001929 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04001930 }
1931 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001932 if ipProto, ok := classifierInfo[IPProto]; ok {
1933 if ipProto.(uint32) == IPProtoDhcp {
1934 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05301935 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001936 logger.Debug("trap-dhcp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01001937 return f.addDHCPTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001938 }
1939 }
1940 }
1941 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001942 if isIgmpTrapDownstreamFlow(classifierInfo) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001943 logger.Debug("trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01001944 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001945 }
A R Karthick1f85b802019-10-11 05:06:05 +00001946
1947 f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
npujarec5762e2020-01-01 14:08:48 +05301948 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00001949
Chaitrashree G S90a17952019-11-14 21:51:21 -05001950 TpID, err := getTpIDFromFlow(flow)
1951 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001952 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 -05001953 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001954 logger.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001955 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07001956 UsMeterID = flows.GetMeterIdFromFlow(flow)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001957 logger.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001958 } else {
Scott Baker355d1742019-10-24 10:57:52 -07001959 DsMeterID = flows.GetMeterIdFromFlow(flow)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001960 logger.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001961
1962 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301963
1964 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
1965 if _, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001966 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 +05301967 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05301968 } else {
Girish Gowdra3d633032019-12-10 16:37:05 +05301969 pendingFlowDelComplete := make(chan bool)
1970 go f.waitForFlowDeletesToCompleteForOnu(ctx, intfID, onuID, uniID, pendingFlowDelComplete)
1971 select {
1972 case <-pendingFlowDelComplete:
Girish Kumar2ad402b2020-03-20 19:45:12 +00001973 logger.Debugw("all pending flow deletes completed", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
npujarec5762e2020-01-01 14:08:48 +05301974 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05301975
1976 case <-time.After(10 * time.Second):
Girish Kumarf26e4882020-03-05 06:49:10 +00001977 return olterrors.NewErrTimeout("pending-flow-deletes", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID}, nil)
Girish Gowdra3d633032019-12-10 16:37:05 +05301978 }
1979 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001980 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001981}
1982
Esin Karamanccb714b2019-11-29 15:02:06 +00001983// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08001984func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00001985 classifierInfo[PacketTagType] = DoubleTag
Girish Kumar2ad402b2020-03-20 19:45:12 +00001986 logger.Debugw("add-multicast-flow", log.Fields{"classifierInfo": classifierInfo, "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00001987
Esin Karaman65409d82020-03-18 10:58:18 +00001988 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00001989 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001990 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00001991 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00001992 //this variable acts like a switch. When it is set, multicast flows are classified by eth_dst.
1993 //otherwise, classification is based on ipv4_dst by default.
1994 //the variable can be configurable in the future; it can be read from a configuration path in the kv store.
1995 mcastFlowClassificationByEthDst := false
1996
1997 if mcastFlowClassificationByEthDst {
1998 //replace ipDst with ethDst
1999 if ipv4Dst, ok := classifierInfo[Ipv4Dst]; ok &&
2000 flows.IsMulticastIp(ipv4Dst.(uint32)) {
2001 // replace ipv4_dst classifier with eth_dst
2002 multicastMac := flows.ConvertToMulticastMacBytes(ipv4Dst.(uint32))
2003 delete(classifierInfo, Ipv4Dst)
2004 classifierInfo[EthDst] = multicastMac
Girish Kumar2ad402b2020-03-20 19:45:12 +00002005 logger.Debugw("multicast-ip-to-mac-conversion-success", log.Fields{"ip:": ipv4Dst.(uint32), "mac:": multicastMac})
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002006 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002007 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002008 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002009
David K. Bainbridge794735f2020-02-11 21:01:37 -08002010 onuID := NoneOnuID
2011 uniID := NoneUniID
2012 gemPortID := NoneGemPortID
Esin Karamanccb714b2019-11-29 15:02:06 +00002013
David K. Bainbridge794735f2020-02-11 21:01:37 -08002014 flowStoreCookie := getFlowStoreCookie(classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05302015 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002016 logger.Debugw("multicast-flow-exists-not-re-adding", log.Fields{"classifierInfo": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002017 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002018 }
npujarec5762e2020-01-01 14:08:48 +05302019 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanccb714b2019-11-29 15:02:06 +00002020 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302021 return olterrors.NewErrNotFound("multicast-flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002022 "interface-id": networkInterfaceID,
2023 "onu-id": onuID,
2024 "uni-id": uniID,
2025 "gem-port-id": gemPortID,
2026 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00002027 err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002028 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002029 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2030 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002031 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002032 }
2033 groupID := actionInfo[GroupID].(uint32)
2034 multicastFlow := openoltpb2.Flow{
2035 FlowId: flowID,
2036 FlowType: Multicast,
2037 NetworkIntfId: int32(networkInterfaceID),
2038 GroupId: groupID,
2039 Classifier: classifierProto,
2040 Priority: int32(flow.Priority),
2041 Cookie: flow.Cookie}
2042
David K. Bainbridge794735f2020-02-11 21:01:37 -08002043 if err = f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002044 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002045 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002046 logger.Debug("multicast flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002047 //get cached group
2048 group, _, err := f.GetFlowGroupFromKVStore(ctx, groupID, true)
2049 if err == nil {
2050 //calling groupAdd to set group members after multicast flow creation
Andrea Campanellac63bba92020-03-10 17:01:04 +01002051 if err = f.ModifyGroup(ctx, group); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002052 //cached group can be removed now
2053 f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002054 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002055 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002056 }
2057 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002058
2059 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &multicastFlow, flowStoreCookie, MulticastFlow, flowID, flow.Id)
2060 if err = f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
2061 int32(onuID),
2062 int32(uniID),
2063 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002064 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002065 }
2066 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002067}
2068
Esin Karaman65409d82020-03-18 10:58:18 +00002069//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2070func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2071 if inPort, ok := classifierInfo[InPort]; ok {
2072 nniInterfaceID, err := IntfIDFromNniPortNum(inPort.(uint32))
2073 if err != nil {
2074 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2075 }
2076 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002077 }
Esin Karaman65409d82020-03-18 10:58:18 +00002078 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302079 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002080 if e == nil && len(nniPorts) > 0 {
2081 return nniPorts[0], nil
2082 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302083 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002084}
2085
2086// AddGroup add or update the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002087func (f *OpenOltFlowMgr) AddGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002088 logger.Infow("add-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002089 if group == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002090 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002091 }
2092
2093 groupToOlt := openoltpb2.Group{
2094 GroupId: group.Desc.GroupId,
2095 Command: openoltpb2.Group_SET_MEMBERS,
2096 Action: f.buildGroupAction(),
2097 }
2098
Girish Kumar2ad402b2020-03-20 19:45:12 +00002099 logger.Debugw("Sending group to device", log.Fields{"groupToOlt": groupToOlt})
npujarec5762e2020-01-01 14:08:48 +05302100 _, err := f.deviceHandler.Client.PerformGroupOperation(ctx, &groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002101 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002102 return olterrors.NewErrAdapter("add-group-operation-failed", log.Fields{"groupToOlt": groupToOlt}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002103 }
2104 // group members not created yet. So let's store the group
npujarec5762e2020-01-01 14:08:48 +05302105 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, true); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002106 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002107 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002108 logger.Debugw("add-group operation performed on the device successfully ", log.Fields{"groupToOlt": groupToOlt})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002109 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002110}
2111
2112//buildGroupAction creates and returns a group action
2113func (f *OpenOltFlowMgr) buildGroupAction() *openoltpb2.Action {
2114 var actionCmd openoltpb2.ActionCmd
2115 var action openoltpb2.Action
2116 action.Cmd = &actionCmd
2117 //pop outer vlan
2118 action.Cmd.RemoveOuterTag = true
2119 return &action
2120}
2121
2122// ModifyGroup updates the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002123func (f *OpenOltFlowMgr) ModifyGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002124 logger.Infow("modify-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002125 if group == nil || group.Desc == nil {
Jonathan Hartc4b19112020-04-02 11:21:45 -07002126 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002127 }
2128
Andrea Campanellac63bba92020-03-10 17:01:04 +01002129 newGroup := f.buildGroup(group.Desc.GroupId, group.Desc.Buckets)
Esin Karamanccb714b2019-11-29 15:02:06 +00002130 //get existing members of the group
npujarec5762e2020-01-01 14:08:48 +05302131 val, groupExists, err := f.GetFlowGroupFromKVStore(ctx, group.Desc.GroupId, false)
Esin Karamanccb714b2019-11-29 15:02:06 +00002132
2133 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002134 return olterrors.NewErrNotFound("flow-group-in-kv-store", log.Fields{"groupId": group.Desc.GroupId}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002135 }
2136
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002137 var current *openoltpb2.Group // represents the group on the device
Esin Karamanccb714b2019-11-29 15:02:06 +00002138 if groupExists {
2139 // group already exists
2140 current = f.buildGroup(group.Desc.GroupId, val.Desc.GetBuckets())
Girish Kumar2ad402b2020-03-20 19:45:12 +00002141 logger.Debugw("modify-group: group exists.", log.Fields{"group on the device": val, "new": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002142 } else {
2143 current = f.buildGroup(group.Desc.GroupId, nil)
2144 }
2145
Girish Kumar2ad402b2020-03-20 19:45:12 +00002146 logger.Debugw("modify-group: comparing current and new.", log.Fields{"group on the device": current, "new": newGroup})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002147 // get members to be added
Andrea Campanellac63bba92020-03-10 17:01:04 +01002148 membersToBeAdded := f.findDiff(current, newGroup)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002149 // get members to be removed
Andrea Campanellac63bba92020-03-10 17:01:04 +01002150 membersToBeRemoved := f.findDiff(newGroup, current)
Esin Karamanccb714b2019-11-29 15:02:06 +00002151
Girish Kumar2ad402b2020-03-20 19:45:12 +00002152 logger.Infow("modify-group -> differences found", log.Fields{"membersToBeAdded": membersToBeAdded,
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002153 "membersToBeRemoved": membersToBeRemoved, "groupId": group.Desc.GroupId})
Esin Karamanccb714b2019-11-29 15:02:06 +00002154
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002155 groupToOlt := openoltpb2.Group{
2156 GroupId: group.Desc.GroupId,
2157 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002158 var errAdd, errRemoved error
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002159 if membersToBeAdded != nil && len(membersToBeAdded) > 0 {
2160 groupToOlt.Command = openoltpb2.Group_ADD_MEMBERS
2161 groupToOlt.Members = membersToBeAdded
2162 //execute addMembers
Andrea Campanellac63bba92020-03-10 17:01:04 +01002163 errAdd = f.callGroupAddRemove(&groupToOlt)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002164 }
2165 if membersToBeRemoved != nil && len(membersToBeRemoved) > 0 {
2166 groupToOlt.Command = openoltpb2.Group_REMOVE_MEMBERS
2167 groupToOlt.Members = membersToBeRemoved
2168 //execute removeMembers
Andrea Campanellac63bba92020-03-10 17:01:04 +01002169 errRemoved = f.callGroupAddRemove(&groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002170 }
2171
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002172 //save the modified group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002173 if errAdd == nil && errRemoved == nil {
npujarec5762e2020-01-01 14:08:48 +05302174 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, false); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002175 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002176 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002177 logger.Debugw("modify-group was success. Storing the group", log.Fields{"group": group, "existingGroup": current})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002178 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002179 logger.Warnw("One of the group add/remove operations has failed. Cannot save group modifications",
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002180 log.Fields{"group": group})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002181 if errAdd != nil {
2182 return errAdd
2183 }
2184 return errRemoved
Esin Karamanccb714b2019-11-29 15:02:06 +00002185 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002186 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002187}
2188
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002189//callGroupAddRemove performs add/remove buckets operation for the indicated group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002190func (f *OpenOltFlowMgr) callGroupAddRemove(group *openoltpb2.Group) error {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002191 if err := f.performGroupOperation(group); err != nil {
2192 st, _ := status.FromError(err)
2193 //ignore already exists error code
2194 if st.Code() != codes.AlreadyExists {
Andrea Campanellac63bba92020-03-10 17:01:04 +01002195 return olterrors.NewErrGroupOp("groupAddRemove", group.GroupId, log.Fields{"status": st}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002196 }
2197 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002198 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002199}
2200
2201//findDiff compares group members and finds members which only exists in groups2
2202func (f *OpenOltFlowMgr) findDiff(group1 *openoltpb2.Group, group2 *openoltpb2.Group) []*openoltpb2.GroupMember {
2203 var members []*openoltpb2.GroupMember
2204 for _, bucket := range group2.Members {
2205 if !f.contains(group1.Members, bucket) {
2206 // bucket does not exist and must be added
2207 members = append(members, bucket)
2208 }
2209 }
2210 return members
2211}
2212
2213//contains returns true if the members list contains the given member; false otherwise
2214func (f *OpenOltFlowMgr) contains(members []*openoltpb2.GroupMember, member *openoltpb2.GroupMember) bool {
2215 for _, groupMember := range members {
2216 if groupMember.InterfaceId == member.InterfaceId {
2217 return true
2218 }
2219 }
2220 return false
2221}
2222
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002223//performGroupOperation call performGroupOperation operation of openolt proto
2224func (f *OpenOltFlowMgr) performGroupOperation(group *openoltpb2.Group) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002225 logger.Debugw("Sending group to device", log.Fields{"groupToOlt": group, "command": group.Command})
Esin Karamanccb714b2019-11-29 15:02:06 +00002226 _, err := f.deviceHandler.Client.PerformGroupOperation(context.Background(), group)
2227 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002228 return olterrors.NewErrAdapter("group-operation-failed", log.Fields{"groupToOlt": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002229 }
Girish Kumarf26e4882020-03-05 06:49:10 +00002230 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002231}
2232
2233//buildGroup build openoltpb2.Group from given group id and bucket list
2234func (f *OpenOltFlowMgr) buildGroup(groupID uint32, buckets []*ofp.OfpBucket) *openoltpb2.Group {
2235 group := openoltpb2.Group{
2236 GroupId: groupID}
2237 // create members of the group
2238 if buckets != nil {
2239 for _, ofBucket := range buckets {
2240 member := f.buildMember(ofBucket)
2241 if member != nil && !f.contains(group.Members, member) {
2242 group.Members = append(group.Members, member)
2243 }
2244 }
2245 }
2246 return &group
2247}
2248
2249//buildMember builds openoltpb2.GroupMember from an OpenFlow bucket
2250func (f *OpenOltFlowMgr) buildMember(ofBucket *ofp.OfpBucket) *openoltpb2.GroupMember {
2251 var outPort uint32
2252 outPortFound := false
2253 for _, ofAction := range ofBucket.Actions {
2254 if ofAction.Type == ofp.OfpActionType_OFPAT_OUTPUT {
2255 outPort = ofAction.GetOutput().Port
2256 outPortFound = true
2257 }
2258 }
2259
2260 if !outPortFound {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002261 logger.Debugw("bucket skipped since no out port found in it",
Esin Karamanccb714b2019-11-29 15:02:06 +00002262 log.Fields{"ofBucket": ofBucket})
2263 return nil
2264 }
2265 interfaceID := IntfIDFromUniPortNum(outPort)
Girish Kumar2ad402b2020-03-20 19:45:12 +00002266 logger.Debugw("got associated interface id of the port", log.Fields{"portNumber:": outPort, "interfaceId:": interfaceID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002267 if groupInfo, ok := f.interfaceToMcastQueueMap[interfaceID]; ok {
2268 member := openoltpb2.GroupMember{
2269 InterfaceId: interfaceID,
2270 InterfaceType: openoltpb2.GroupMember_PON,
2271 GemPortId: groupInfo.gemPortID,
2272 Priority: groupInfo.servicePriority,
2273 }
2274 //add member to the group
2275 return &member
2276 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002277 logger.Warnf("bucket skipped since interface-2-gem mapping cannot be found",
Esin Karamanccb714b2019-11-29 15:02:06 +00002278 log.Fields{"ofBucket": ofBucket})
2279 return nil
2280}
2281
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002282//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04002283func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002284
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002285 onuDev, err := f.getOnuDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302286 if err != nil {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002287 logger.Errorw("couldnt-find-onu-child-device", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
2288 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302289 }
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002290 logger.Debugw("Got child device from OLT device handler", log.Fields{"deviceId": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002291
Manikkaraj kb1d51442019-07-23 10:41:02 -04002292 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002293 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Girish Kumar2ad402b2020-03-20 19:45:12 +00002294 logger.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
manikkaraj k17652a72019-05-06 09:06:36 -04002295 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
2296 tpDownloadMsg,
2297 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
2298 f.deviceHandler.deviceType,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002299 onuDev.deviceType,
2300 onuDev.deviceID,
2301 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002302 if sendErr != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002303 return olterrors.NewErrCommunication("send-techprofile-download-request", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002304 "toAdapter": onuDev.deviceType, "onuId": onuDev.deviceID,
2305 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002306 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002307 logger.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302308 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302309}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002310
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302311//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002312func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302313
2314 f.lockCache.Lock()
2315 defer f.lockCache.Unlock()
2316 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2317 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002318 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002319 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302320 }
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002321 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 +02002322 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002323}
2324
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302325//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302326func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302327 f.lockCache.Lock()
2328 defer f.lockCache.Unlock()
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002329 logger.Debugw("adding-gem-to-onu-info-map",
2330 log.Fields{"gem": gemPort, "intf": intfID, "onu": onuID, "deviceId": f.deviceHandler.device.Id, "onuGem": f.onuGemInfo[intfID]})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302331 onugem := f.onuGemInfo[intfID]
2332 // update the gem to the local cache as well as to kv strore
2333 for idx, onu := range onugem {
2334 if onu.OnuID == onuID {
2335 // check if gem already exists , else update the cache and kvstore
2336 for _, gem := range onu.GemPorts {
2337 if gem == gemPort {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002338 logger.Debugw("gem-already-in-cache-no-need-to-update-cache-and-kv-store",
2339 log.Fields{"gem": gemPort, "deviceId": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302340 return
2341 }
2342 }
2343 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
2344 f.onuGemInfo[intfID] = onugem
2345 }
2346 }
npujarec5762e2020-01-01 14:08:48 +05302347 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302348 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002349 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 -04002350 return
2351 }
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002352 logger.Debugw("gem-added-to-onu-info-map",
2353 log.Fields{"gem": gemPort, "intf": intfID, "onu": onuID, "deviceId": f.deviceHandler.device.Id, "onuGem": f.onuGemInfo[intfID]})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002354}
2355
2356// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002357
2358//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
2359func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302360
2361 f.lockCache.Lock()
2362 defer f.lockCache.Unlock()
2363
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002364 logger.Debugw("Getting-ONU-ID-from-GEM-port-and-PON-port", log.Fields{
2365 "deviceId": f.deviceHandler.device.Id, "onuGemInfo": f.onuGemInfo[intfID],
2366 "serialNumber": serialNumber, "intfId": intfID, "gemPortId": gemPortID})
2367
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302368 // get onuid from the onugem info cache
2369 onugem := f.onuGemInfo[intfID]
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002370
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302371 for _, onu := range onugem {
2372 for _, gem := range onu.GemPorts {
2373 if gem == gemPortID {
2374 return onu.OnuID, nil
2375 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002376 }
2377 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302378 return uint32(0), olterrors.NewErrNotFound("onu-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002379 "serial-number": serialNumber,
2380 "interface-id": intfID,
2381 "gem-port-id": gemPortID},
Girish Kumarf26e4882020-03-05 06:49:10 +00002382 nil)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002383}
2384
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002385//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302386func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002387 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002388 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002389 var err error
2390
2391 if packetIn.IntfType == "pon" {
2392 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002393 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002394 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002395 return logicalPortNum, err
2396 }
2397 if packetIn.PortNo != 0 {
2398 logicalPortNum = packetIn.PortNo
2399 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002400 uniID := uint32(0) // FIXME - multi-uni support
2401 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002402 }
2403 // Store the gem port through which the packet_in came. Use the same gem port for packet_out
npujarec5762e2020-01-01 14:08:48 +05302404 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002405 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002406 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002407 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002408 logger.Debugw("Retrieved logicalport from packet-in", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08002409 "logicalPortNum": logicalPortNum,
2410 "IntfType": packetIn.IntfType,
2411 "packet": hex.EncodeToString(packetIn.Pkt),
2412 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002413 return logicalPortNum, nil
2414}
2415
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002416//GetPacketOutGemPortID returns gemPortId
npujarec5762e2020-01-01 14:08:48 +05302417func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002418 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002419 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302420
2421 f.lockCache.Lock()
2422 defer f.lockCache.Unlock()
2423 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum}
2424
2425 gemPortID, ok := f.packetInGemPort[pktInkey]
2426 if ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002427 logger.Debugw("Found gemport for pktin key", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302428 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002429 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302430 //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 +05302431 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, intfID, onuID, portNum)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302432 if err == nil {
2433 if gemPortID != 0 {
2434 f.packetInGemPort[pktInkey] = gemPortID
Girish Kumar2ad402b2020-03-20 19:45:12 +00002435 logger.Debugw("Found gem port from kv store and updating cache with gemport",
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302436 log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
2437 return gemPortID, nil
2438 }
2439 }
Girish Kumarf26e4882020-03-05 06:49:10 +00002440 return uint32(0), olterrors.NewErrNotFound("gem-port", log.Fields{"pktinkey": pktInkey, "gem": gemPortID}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002441}
2442
npujarec5762e2020-01-01 14:08:48 +05302443func installFlowOnAllGemports(ctx context.Context,
2444 f1 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32,
Manikkaraj kb1d51442019-07-23 10:41:02 -04002445 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002446 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, tpID uint32) error,
npujarec5762e2020-01-01 14:08:48 +05302447 f2 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05302448 classifier map[string]interface{}, action map[string]interface{},
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302449 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002450 tpID uint32) error,
Manikkaraj kb1d51442019-07-23 10:41:02 -04002451 args map[string]uint32,
2452 classifier map[string]interface{}, action map[string]interface{},
2453 logicalFlow *ofp.OfpFlowStats,
2454 gemPorts []uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05302455 TpInst *tp.TechProfile,
Manikkaraj kb1d51442019-07-23 10:41:02 -04002456 FlowType string,
Gamze Abaka724d0852020-03-18 12:10:24 +00002457 direction string,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002458 tpID uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +00002459 vlanID ...uint32) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002460 logger.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
Girish Gowdrafae935c2020-02-17 19:21:44 +05302461
Gamze Abaka724d0852020-03-18 12:10:24 +00002462 // The bit mapping for a gemport is expressed in tech-profile as a binary string. For example, 0b00000001
2463 // We need to trim prefix "0b", before further processing
2464 // Once the "0b" prefix is trimmed, we iterate each character in the string to identify which index
2465 // in the string is set to binary bit 1 (expressed as char '1' in the binary string).
2466
2467 // If a particular character in the string is set to '1', identify the index of this character from
2468 // the LSB position which marks the PCP bit consumed by the given gem port.
2469 // This PCP bit now becomes a classifier in the flow.
2470
2471 attributes := TpInst.DownstreamGemPortAttributeList
2472 if direction == Upstream {
2473 attributes = TpInst.UpstreamGemPortAttributeList
2474 }
2475
2476 for _, gemPortAttribute := range attributes {
2477 if direction == Downstream && strings.ToUpper(gemPortAttribute.IsMulticast) == "TRUE" {
2478 continue
2479 }
2480 gemPortID := gemPortAttribute.GemportID
2481 if allPbitsMarked(gemPortAttribute.PbitMap) {
2482 classifier[VlanPcp] = uint32(VlanPCPMask)
2483 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002484 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
Gamze Abaka724d0852020-03-18 12:10:24 +00002485 } else if FlowType == EapolFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002486 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
Gamze Abaka724d0852020-03-18 12:10:24 +00002487 }
2488 } else {
2489 for pos, pbitSet := range strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix) {
2490 if pbitSet == BinaryBit1 {
2491 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
2492 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002493 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
Gamze Abaka724d0852020-03-18 12:10:24 +00002494 } else if FlowType == EapolFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002495 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
Gamze Abaka724d0852020-03-18 12:10:24 +00002496 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05302497 }
2498 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002499 }
2500 }
2501}
2502
Gamze Abaka724d0852020-03-18 12:10:24 +00002503func allPbitsMarked(pbitMap string) bool {
2504 for pos, pBit := range pbitMap {
2505 if pos >= 2 && pBit != BinaryBit1 {
2506 return false
2507 }
2508 }
2509 return true
2510}
2511
David K. Bainbridge794735f2020-02-11 21:01:37 -08002512func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002513 logger.Debug("Adding trap-dhcp-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002514 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002515 classifier[PacketTagType] = DoubleTag
2516 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002517 /* We manage flowId resource pool on per PON port basis.
2518 Since this situation is tricky, as a hack, we pass the NNI port
2519 index (network_intf_id) as PON port Index for the flowId resource
2520 pool. Also, there is no ONU Id available for trapping DHCP packets
2521 on NNI port, use onu_id as -1 (invalid)
2522 ****************** CAVEAT *******************
2523 This logic works if the NNI Port Id falls within the same valid
2524 range of PON Port Ids. If this doesn't work for some OLT Vendor
2525 we need to have a re-look at this.
2526 *********************************************
2527 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002528 onuID := -1
2529 uniID := -1
2530 gemPortID := -1
2531 allocID := -1
David K. Bainbridge794735f2020-02-11 21:01:37 -08002532 networkInterfaceID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302533 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302534 return olterrors.NewErrNotFound("nni-intreface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002535 "classifier": classifier,
2536 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002537 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302538 }
2539
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002540 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05302541 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002542 logger.Debug("Flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002543 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002544 }
Gamze Abaka724d0852020-03-18 12:10:24 +00002545 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002546 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302547 return olterrors.NewErrNotFound("dhcp-trap-nni-flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002548 "interface-id": networkInterfaceID,
2549 "onu-id": onuID,
2550 "uni-id": uniID,
2551 "gem-port-id": gemPortID,
2552 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00002553 err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002554 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002555 classifierProto, err := makeOpenOltClassifierField(classifier)
2556 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002557 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002558 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002559 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002560 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002561 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002562 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002563 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002564 logger.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002565 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2566 OnuId: int32(onuID), // OnuId not required
2567 UniId: int32(uniID), // UniId not used
2568 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002569 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002570 AllocId: int32(allocID), // AllocId not used
2571 NetworkIntfId: int32(networkInterfaceID),
2572 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002573 Classifier: classifierProto,
2574 Action: actionProto,
2575 Priority: int32(logicalFlow.Priority),
2576 Cookie: logicalFlow.Cookie,
2577 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002578 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002579 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002580 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002581 logger.Debug("DHCP trap on NNI flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002582 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
2583 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
2584 int32(onuID),
2585 int32(uniID),
2586 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002587 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002588 }
2589 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002590}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002591
Esin Karamanae41e2b2019-12-17 18:13:13 +00002592//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2593func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2594 var packetType string
2595 ovid, ivid := false, false
2596 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2597 vid := vlanID & VlanvIDMask
2598 if vid != ReservedVlan {
2599 ovid = true
2600 }
2601 }
2602 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2603 vid := uint32(metadata)
2604 if vid != ReservedVlan {
2605 ivid = true
2606 }
2607 }
2608 if ovid && ivid {
2609 packetType = DoubleTag
2610 } else if !ovid && !ivid {
2611 packetType = Untagged
2612 } else {
2613 packetType = SingleTag
2614 }
2615 return packetType
2616}
2617
2618//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002619func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002620 logger.Debugw("Adding igmp-trap-of-nni-flow", log.Fields{"classifierInfo": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002621 action := make(map[string]interface{})
2622 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2623 action[TrapToHost] = true
2624 /* We manage flowId resource pool on per PON port basis.
2625 Since this situation is tricky, as a hack, we pass the NNI port
2626 index (network_intf_id) as PON port Index for the flowId resource
2627 pool. Also, there is no ONU Id available for trapping packets
2628 on NNI port, use onu_id as -1 (invalid)
2629 ****************** CAVEAT *******************
2630 This logic works if the NNI Port Id falls within the same valid
2631 range of PON Port Ids. If this doesn't work for some OLT Vendor
2632 we need to have a re-look at this.
2633 *********************************************
2634 */
2635 onuID := -1
2636 uniID := -1
2637 gemPortID := -1
2638 allocID := -1
2639 networkInterfaceID, err := getNniIntfID(classifier, action)
2640 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302641 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002642 "classifier": classifier,
2643 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002644 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002645 }
2646 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05302647 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002648 logger.Debug("igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002649 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002650 }
npujarec5762e2020-01-01 14:08:48 +05302651 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002652 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302653 return olterrors.NewErrNotFound("igmp-flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002654 "interface-id": networkInterfaceID,
2655 "onu-id": onuID,
2656 "uni-id": uniID,
2657 "gem-port-id": gemPortID,
2658 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00002659 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002660 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002661 classifierProto, err := makeOpenOltClassifierField(classifier)
2662 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002663 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002664 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002665 logger.Debugw("Created classifier proto for the IGMP flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002666 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002667 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002668 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002669 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002670 logger.Debugw("Created action proto for the IGMP flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002671 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2672 OnuId: int32(onuID), // OnuId not required
2673 UniId: int32(uniID), // UniId not used
2674 FlowId: flowID,
2675 FlowType: Downstream,
2676 AllocId: int32(allocID), // AllocId not used
2677 NetworkIntfId: int32(networkInterfaceID),
2678 GemportId: int32(gemPortID), // GemportId not used
2679 Classifier: classifierProto,
2680 Action: actionProto,
2681 Priority: int32(logicalFlow.Priority),
2682 Cookie: logicalFlow.Cookie,
2683 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002684 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002685 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002686 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002687 logger.Debug("IGMP Trap on NNI flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002688 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
2689 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
2690 int32(onuID),
2691 int32(uniID),
2692 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002693 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002694 }
2695 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002696}
2697
salmansiddiqui7ac62132019-08-22 03:58:50 +00002698func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2699 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302700 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002701 }
2702 if Dir == tp_pb.Direction_UPSTREAM {
2703 return "upstream", nil
2704 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2705 return "downstream", nil
2706 }
2707 return "", nil
2708}
2709
npujarec5762e2020-01-01 14:08:48 +05302710func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Gamze Abakafee36392019-10-03 11:17:24 +00002711 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst *tp.TechProfile, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002712 tpID uint32, uni string) {
Gamze Abakafee36392019-10-03 11:17:24 +00002713 var gemPort uint32
2714 intfID := args[IntfID]
2715 onuID := args[OnuID]
2716 uniID := args[UniID]
2717 portNo := args[PortNo]
2718 allocID := TpInst.UsScheduler.AllocID
salmansiddiqui7ac62132019-08-22 03:58:50 +00002719 if ipProto, ok := classifierInfo[IPProto]; ok {
2720 if ipProto.(uint32) == IPProtoDhcp {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002721 logger.Info("Adding DHCP flow")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002722 if pcp, ok := classifierInfo[VlanPcp]; ok {
2723 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2724 tp_pb.Direction_UPSTREAM,
2725 pcp.(uint32))
2726 //Adding DHCP upstream flow
Gamze Abaka724d0852020-03-18 12:10:24 +00002727
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002728 f.addDHCPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002729 } else {
2730 //Adding DHCP upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002731 installFlowOnAllGemports(ctx, f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, DhcpFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002732 }
2733
Girish Gowdra32625212020-04-29 11:26:35 -07002734 } else if ipProto.(uint32) == IgmpProto {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002735 logger.Infow("Adding Us IGMP flow", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "classifierInfo:": classifierInfo})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002736 if pcp, ok := classifierInfo[VlanPcp]; ok {
2737 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2738 tp_pb.Direction_UPSTREAM,
2739 pcp.(uint32))
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002740 f.addIGMPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002741 } else {
2742 //Adding IGMP upstream flow to all gem ports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002743 installFlowOnAllGemports(ctx, f.addIGMPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, IgmpFlow, Upstream, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002744 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002745 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002746 logger.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002747 return
2748 }
2749 } else if ethType, ok := classifierInfo[EthType]; ok {
2750 if ethType.(uint32) == EapEthType {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002751 logger.Info("Adding EAPOL flow")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002752 var vlanID uint32
2753 if val, ok := classifierInfo[VlanVid]; ok {
2754 vlanID = (val.(uint32)) & VlanvIDMask
2755 } else {
2756 vlanID = DefaultMgmtVlan
2757 }
2758 if pcp, ok := classifierInfo[VlanPcp]; ok {
2759 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2760 tp_pb.Direction_UPSTREAM,
2761 pcp.(uint32))
2762
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002763 f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002764 } else {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002765 installFlowOnAllGemports(ctx, nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, EapolFlow, Upstream, tpID, vlanID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002766 }
2767 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002768 } else if _, ok := actionInfo[PushVlan]; ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002769 logger.Info("Adding upstream data rule")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002770 if pcp, ok := classifierInfo[VlanPcp]; ok {
2771 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2772 tp_pb.Direction_UPSTREAM,
2773 pcp.(uint32))
2774 //Adding HSIA upstream flow
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002775 f.addUpstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002776 } else {
2777 //Adding HSIA upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002778 installFlowOnAllGemports(ctx, f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002779 }
2780 } else if _, ok := actionInfo[PopVlan]; ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002781 logger.Info("Adding Downstream data rule")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002782 if pcp, ok := classifierInfo[VlanPcp]; ok {
2783 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05002784 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00002785 pcp.(uint32))
2786 //Adding HSIA downstream flow
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002787 f.addDownstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002788 } else {
2789 //Adding HSIA downstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002790 installFlowOnAllGemports(ctx, f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Downstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002791 }
2792 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002793 logger.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002794 return
2795 }
2796 // Send Techprofile download event to child device in go routine as it takes time
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002797 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002798}
2799
Gamze Abakafee36392019-10-03 11:17:24 +00002800func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
2801 flowIDList := f.flowsUsedByGemPort[gemPK]
2802 if len(flowIDList) > 1 {
2803 return true
2804 }
2805 return false
2806}
2807
npujarec5762e2020-01-01 14:08:48 +05302808func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
2809 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002810 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2811 for _, currentGemPort := range currentGemPorts {
2812 for _, tpGemPort := range tpGemPorts {
2813 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
2814 return true, currentGemPort
2815 }
2816 }
2817 }
Girish Gowdra54934262019-11-13 14:19:55 +05302818 if tpInst.InstanceCtrl.Onu == "single-instance" {
2819 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
npujarec5762e2020-01-01 14:08:48 +05302820 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, uint32(onuID), uint32(uniID), tpID)
2821 f.DeleteTechProfileInstance(ctx, ponIntf, uint32(onuID), uint32(uniID), "", tpID)
Girish Gowdra54934262019-11-13 14:19:55 +05302822
2823 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
2824 // still be used on other uni ports.
2825 // So, we need to check and make sure that no other gem port is referring to the given TP ID
2826 // on any other uni port.
npujarec5762e2020-01-01 14:08:48 +05302827 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID)
Girish Kumar2ad402b2020-03-20 19:45:12 +00002828 logger.Debugw("got single instance tp instances", log.Fields{"tpInstances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05302829 for i := 0; i < len(tpInstances); i++ {
2830 tpI := tpInstances[i]
2831 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05302832 for _, tpGemPort := range tpGemPorts {
2833 if tpGemPort.GemportID != gemPortID {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002834 logger.Debugw("single instance tp is in use by gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302835 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05302836 }
2837 }
2838 }
2839 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002840 logger.Debug("tech profile is not in use by any gem")
Gamze Abakafee36392019-10-03 11:17:24 +00002841 return false, 0
2842}
2843
salmansiddiqui7ac62132019-08-22 03:58:50 +00002844func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002845 for _, field := range flows.GetOfbFields(flow) {
2846 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002847 classifierInfo[EthType] = field.GetEthType()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002848 logger.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002849 } else if field.Type == flows.ETH_DST {
2850 classifierInfo[EthDst] = field.GetEthDst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002851 logger.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07002852 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002853 classifierInfo[IPProto] = field.GetIpProto()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002854 logger.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002855 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002856 classifierInfo[InPort] = field.GetPort()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002857 logger.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002858 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05302859 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Girish Kumar2ad402b2020-03-20 19:45:12 +00002860 logger.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002861 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002862 classifierInfo[VlanPcp] = field.GetVlanPcp()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002863 logger.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002864 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002865 classifierInfo[UDPDst] = field.GetUdpDst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002866 logger.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002867 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002868 classifierInfo[UDPSrc] = field.GetUdpSrc()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002869 logger.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002870 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002871 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002872 logger.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002873 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002874 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002875 logger.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002876 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002877 classifierInfo[Metadata] = field.GetTableMetadata()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002878 logger.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07002879 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002880 classifierInfo[TunnelID] = field.GetTunnelId()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002881 logger.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002882 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002883 logger.Errorw("Un supported field type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002884 return
2885 }
2886 }
2887}
2888
2889func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07002890 for _, action := range flows.GetActions(flow) {
2891 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002892 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002893 actionInfo[Output] = out.GetPort()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002894 logger.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002895 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002896 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002897 }
Scott Baker355d1742019-10-24 10:57:52 -07002898 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002899 actionInfo[PopVlan] = true
Girish Kumar2ad402b2020-03-20 19:45:12 +00002900 logger.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002901 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002902 if out := action.GetPush(); out != nil {
2903 if tpid := out.GetEthertype(); tpid != 0x8100 {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002904 logger.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002905 } else {
2906 actionInfo[PushVlan] = true
2907 actionInfo[TPID] = tpid
Girish Kumar2ad402b2020-03-20 19:45:12 +00002908 logger.Debugw("action-type-push-vlan",
salmansiddiqui7ac62132019-08-22 03:58:50 +00002909 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
2910 }
2911 }
Scott Baker355d1742019-10-24 10:57:52 -07002912 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002913 if out := action.GetSetField(); out != nil {
2914 if field := out.GetField(); field != nil {
2915 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00002916 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002917 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002918 /*logger.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
Esin Karamanccb714b2019-11-29 15:02:06 +00002919 formulateSetFieldActionInfoFromFlow(field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002920 }
2921 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002922 } else if action.Type == flows.GROUP {
2923 formulateGroupActionInfoFromFlow(action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002924 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002925 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002926 }
2927 }
2928 return nil
2929}
2930
Esin Karamanccb714b2019-11-29 15:02:06 +00002931func formulateSetFieldActionInfoFromFlow(field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
2932 if ofbField := field.GetOfbField(); ofbField != nil {
2933 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
2934 if vlan := ofbField.GetVlanVid(); vlan != 0 {
2935 actionInfo[VlanVid] = vlan & 0xfff
Girish Kumar2ad402b2020-03-20 19:45:12 +00002936 logger.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002937 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002938 logger.Error("No Invalid vlan id in set vlan-vid action")
Esin Karamanccb714b2019-11-29 15:02:06 +00002939 }
2940 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002941 logger.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00002942 }
2943 }
2944}
2945
2946func formulateGroupActionInfoFromFlow(action *ofp.OfpAction, actionInfo map[string]interface{}) {
2947 if action.GetGroup() == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002948 logger.Warn("No group entry found in the group action")
Esin Karamanccb714b2019-11-29 15:02:06 +00002949 } else {
2950 actionInfo[GroupID] = action.GetGroup().GroupId
Girish Kumar2ad402b2020-03-20 19:45:12 +00002951 logger.Debugw("action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002952 }
2953}
2954
salmansiddiqui7ac62132019-08-22 03:58:50 +00002955func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002956 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002957 logger.Debug("Controller bound trap flows, getting inport from tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002958 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2959 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002960 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002961 classifierInfo[InPort] = uniPort
Girish Kumar2ad402b2020-03-20 19:45:12 +00002962 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 +00002963 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +05302964 return olterrors.NewErrNotFound("child-in-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002965 "reason": "upstream pon-to-controller-flow, NO-inport-in-tunnelid",
Girish Kumarf26e4882020-03-05 06:49:10 +00002966 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002967 }
2968 }
2969 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002970 logger.Debug("Non-Controller flows, getting uniport from tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002971 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07002972 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002973 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002974 actionInfo[Output] = uniPort
Girish Kumar2ad402b2020-03-20 19:45:12 +00002975 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 +00002976 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +05302977 return olterrors.NewErrNotFound("out-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002978 "reason": "downstream-nni-to-pon-port-flow, no-outport-in-tunnelid",
Girish Kumarf26e4882020-03-05 06:49:10 +00002979 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002980 }
2981 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2982 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002983 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002984 classifierInfo[InPort] = uniPort
Girish Kumar2ad402b2020-03-20 19:45:12 +00002985 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 -07002986 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002987 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +05302988 return olterrors.NewErrNotFound("nni-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002989 "reason": "upstream-pon-to-nni-port-flow, no-inport-in-tunnelid",
2990 "in-port": classifierInfo[InPort].(uint32),
2991 "out-port": actionInfo[Output].(uint32),
Girish Kumarf26e4882020-03-05 06:49:10 +00002992 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002993 }
2994 }
2995 }
2996 return nil
2997}
Gamze Abakafee36392019-10-03 11:17:24 +00002998
Chaitrashree G S90a17952019-11-14 21:51:21 -05002999func getTpIDFromFlow(flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003000 /* Metadata 8 bytes:
3001 Most Significant 2 Bytes = Inner VLAN
3002 Next 2 Bytes = Tech Profile ID(TPID)
3003 Least Significant 4 Bytes = Port ID
3004 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3005 subscriber related flows.
3006 */
3007 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
3008 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003009 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003010 }
3011 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003012 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003013}
3014
3015func appendUnique(slice []uint32, item uint32) []uint32 {
3016 for _, sliceElement := range slice {
3017 if sliceElement == item {
3018 return slice
3019 }
3020 }
3021 return append(slice, item)
3022}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303023
3024// getNniIntfID gets nni intf id from the flow classifier/action
3025func getNniIntfID(classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
3026
3027 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3028 if portType == voltha.Port_PON_OLT {
David K. Bainbridge794735f2020-02-11 21:01:37 -08003029 intfID, err := IntfIDFromNniPortNum(action[Output].(uint32))
3030 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003031 logger.Debugw("invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003032 log.Fields{
3033 "port-number": action[Output].(uint32),
3034 "error": err})
3035 return uint32(0), err
3036 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00003037 logger.Debugw("output Nni IntfID is", log.Fields{"intfid": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303038 return intfID, nil
3039 } else if portType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08003040 intfID, err := IntfIDFromNniPortNum(classifier[InPort].(uint32))
3041 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003042 logger.Debugw("invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003043 log.Fields{
3044 "port-number": action[Output].(uint32),
3045 "error": err})
3046 return uint32(0), err
3047 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00003048 logger.Debugw("input Nni IntfID is", log.Fields{"intfid": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303049 return intfID, nil
3050 }
3051 return uint32(0), nil
3052}
3053
3054// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
npujarec5762e2020-01-01 14:08:48 +05303055func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303056 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort}
3057
3058 f.lockCache.Lock()
3059 defer f.lockCache.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003060 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303061 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003062 if lookupGemPort == gemPort {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003063 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 -05003064 log.Fields{"pktinkey": pktInkey, "gem": gemPort})
3065 return
3066 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303067 }
Matt Jeanneret1719a072019-12-20 14:50:14 -05003068 f.packetInGemPort[pktInkey] = gemPort
3069
npujarec5762e2020-01-01 14:08:48 +05303070 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Girish Kumar2ad402b2020-03-20 19:45:12 +00003071 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 +05303072 return
3073}
3074
3075// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303076func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303077
3078 f.lockCache.Lock()
3079 defer f.lockCache.Unlock()
3080 onugem := f.onuGemInfo[intfID]
3081 for idx, onu := range onugem {
3082 if onu.OnuID == onuID {
3083 for _, uni := range onu.UniPorts {
3084 if uni == portNum {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003085 logger.Debugw("uni already in cache, no need to update cache and kv store",
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303086 log.Fields{"uni": portNum})
3087 return
3088 }
3089 }
3090 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
3091 f.onuGemInfo[intfID] = onugem
3092 }
3093 }
npujarec5762e2020-01-01 14:08:48 +05303094 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303095}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303096
npujarec5762e2020-01-01 14:08:48 +05303097func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3098 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303099 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003100 logger.Error("Failed to get flowid list per gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303101 return
3102 }
3103 for gem, FlowIDs := range flowIDsList {
3104 gemPK := gemPortKey{intf, uint32(gem)}
3105 f.flowsUsedByGemPort[gemPK] = FlowIDs
3106 }
3107 return
3108}
Esin Karamanccb714b2019-11-29 15:02:06 +00003109
3110//loadInterfaceToMulticastQueueMap reads multicast queues per interface from the KV store
3111//and put them into interfaceToMcastQueueMap.
npujarec5762e2020-01-01 14:08:48 +05303112func (f *OpenOltFlowMgr) loadInterfaceToMulticastQueueMap(ctx context.Context) {
3113 storedMulticastQueueMap, err := f.resourceMgr.GetMcastQueuePerInterfaceMap(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00003114 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003115 logger.Error("Failed to get pon interface to multicast queue map")
Esin Karamanccb714b2019-11-29 15:02:06 +00003116 return
3117 }
3118 for intf, queueInfo := range storedMulticastQueueMap {
3119 q := queueInfoBrief{
3120 gemPortID: queueInfo[0],
3121 servicePriority: queueInfo[1],
3122 }
3123 f.interfaceToMcastQueueMap[intf] = &q
3124 }
3125}
3126
3127//GetFlowGroupFromKVStore fetches and returns flow group from the KV store. Returns (nil, false, error) if any problem occurs during
3128//fetching the data. Returns (group, true, nil) if the group is fetched and returned successfully.
3129//Returns (nil, false, nil) if the group does not exists in the KV store.
npujarec5762e2020-01-01 14:08:48 +05303130func (f *OpenOltFlowMgr) GetFlowGroupFromKVStore(ctx context.Context, groupID uint32, cached bool) (*ofp.OfpGroupEntry, bool, error) {
3131 exists, groupInfo, err := f.resourceMgr.GetFlowGroupFromKVStore(ctx, groupID, cached)
Esin Karamanccb714b2019-11-29 15:02:06 +00003132 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003133 return nil, false, olterrors.NewErrNotFound("flow-group", log.Fields{"group-id": groupID}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00003134 }
3135 if exists {
3136 return newGroup(groupInfo.GroupID, groupInfo.OutPorts), exists, nil
3137 }
3138 return nil, exists, nil
3139}
3140
3141func newGroup(groupID uint32, outPorts []uint32) *ofp.OfpGroupEntry {
3142 groupDesc := ofp.OfpGroupDesc{
3143 Type: ofp.OfpGroupType_OFPGT_ALL,
3144 GroupId: groupID,
3145 }
3146 groupEntry := ofp.OfpGroupEntry{
3147 Desc: &groupDesc,
3148 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003149 for i := 0; i < len(outPorts); i++ {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003150 var acts []*ofp.OfpAction
Esin Karamanccb714b2019-11-29 15:02:06 +00003151 acts = append(acts, flows.Output(outPorts[i]))
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003152 bucket := ofp.OfpBucket{
3153 Actions: acts,
3154 }
3155 groupDesc.Buckets = append(groupDesc.Buckets, &bucket)
Esin Karamanccb714b2019-11-29 15:02:06 +00003156 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003157 return &groupEntry
3158}