blob: e4f334900e23e33121471bfb765e390c96ea710c [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 {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000230 logger.Info("Initializing flow manager")
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
Girish Kumar2ad402b2020-03-20 19:45:12 +0000301 logger.Infow("Dividing flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "portNo": portNo,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000302 "classifier": classifierInfo, "action": actionInfo, "UsMeterID": UsMeterID, "DsMeterID": DsMeterID, "TpID": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400303 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
304 // is because the flow is an NNI flow and there would be no onu resources associated with it
305 // TODO: properly deal with NNI flows
Manikkaraj kb1d51442019-07-23 10:41:02 -0400306 if onuID <= 0 {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000307 logger.Errorw("No onu id for flow", log.Fields{"portNo": portNo, "classifer": classifierInfo, "action": actionInfo})
manikkaraj kbf256be2019-03-25 00:13:48 +0530308 return
309 }
310
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530311 uni := getUniPortPath(intfID, int32(onuID), int32(uniID))
Girish Kumar2ad402b2020-03-20 19:45:12 +0000312 logger.Debugw("Uni port name", log.Fields{"uni": uni})
Girish Gowdra3d633032019-12-10 16:37:05 +0530313
314 tpLockMapKey := tpLockKey{intfID, onuID, uniID}
315 if f.perUserFlowHandleLock.TryLock(tpLockMapKey) {
npujarec5762e2020-01-01 14:08:48 +0530316 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +0530317 if allocID == 0 || gemPorts == nil || TpInst == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000318 logger.Error("alloc-id-gem-ports-tp-unavailable")
Girish Gowdra3d633032019-12-10 16:37:05 +0530319 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
320 return
321 }
322 args := make(map[string]uint32)
323 args[IntfID] = intfID
324 args[OnuID] = onuID
325 args[UniID] = uniID
326 args[PortNo] = portNo
327 args[AllocID] = allocID
328
329 /* Flows can be added specific to gemport if p-bits are received.
330 * If no pbit mentioned then adding flows for all gemports
331 */
npujarec5762e2020-01-01 14:08:48 +0530332 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
Girish Gowdra3d633032019-12-10 16:37:05 +0530333 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
334 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000335 logger.Errorw("failed to acquire per user flow handle lock",
Girish Gowdra3d633032019-12-10 16:37:05 +0530336 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400337 return
338 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530339}
340
salmansiddiqui7ac62132019-08-22 03:58:50 +0000341// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530342func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400343
Girish Kumar2ad402b2020-03-20 19:45:12 +0000344 logger.Debugw("CreateSchedulerQueues", log.Fields{"Dir": sq.direction, "IntfID": sq.intfID,
Gamze Abakafee36392019-10-03 11:17:24 +0000345 "OnuID": sq.onuID, "UniID": sq.uniID, "TpID": sq.tpID, "MeterID": sq.meterID,
346 "TpInst": sq.tpInst, "flowMetadata": sq.flowMetadata})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400347
Gamze Abakafee36392019-10-03 11:17:24 +0000348 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000349 if err != nil {
350 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400351 }
352
353 /* Lets make a simple assumption that if the meter-id is present on the KV store,
354 * then the scheduler and queues configuration is applied on the OLT device
355 * in the given direction.
356 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000357
Manikkaraj kb1d51442019-07-23 10:41:02 -0400358 var SchedCfg *tp_pb.SchedulerConfig
npujarec5762e2020-01-01 14:08:48 +0530359 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400360 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000361 return olterrors.NewErrNotFound("meter", log.Fields{"intfId": sq.intfID, "onuId": sq.onuID, "uniId": sq.uniID}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400362 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000363
Manikkaraj kb1d51442019-07-23 10:41:02 -0400364 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000365 if KvStoreMeter.MeterId == sq.meterID {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000366 logger.Debug("Scheduler already created for upstream")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400367 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400368 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530369 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800370 "unsupported": "meter-id",
371 "kv-store-meter-id": KvStoreMeter.MeterId,
Girish Kumarf26e4882020-03-05 06:49:10 +0000372 "meter-id-in-flow": sq.meterID}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400373 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000374
Girish Kumar2ad402b2020-03-20 19:45:12 +0000375 logger.Debugw("Meter-does-not-exist-Creating-new", log.Fields{"MeterID": sq.meterID, "Direction": Direction})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000376
Gamze Abakafee36392019-10-03 11:17:24 +0000377 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000378 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Gamze Abakafee36392019-10-03 11:17:24 +0000379 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000380 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400381 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000382
383 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000384 return olterrors.NewErrNotFound("scheduler-config", log.Fields{"IntfID": sq.intfID, "Direction": sq.direction, "tpInst": sq.tpInst}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000385 }
386
Manikkaraj kb1d51442019-07-23 10:41:02 -0400387 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000388 if sq.flowMetadata != nil {
389 for _, meter := range sq.flowMetadata.Meters {
390 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400391 meterConfig = meter
Girish Kumar2ad402b2020-03-20 19:45:12 +0000392 logger.Debugw("Found-meter-config-from-flowmetadata", log.Fields{"meterConfig": meterConfig})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400393 break
394 }
395 }
396 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000397 logger.Error("Flow-metadata-is-not-present-in-flow")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400398 }
399 if meterConfig == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530400 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800401 "reason": "Could-not-get-meterbands-from-flowMetadata",
402 "flow-metadata": sq.flowMetadata,
Girish Kumarf26e4882020-03-05 06:49:10 +0000403 "meter-id": sq.meterID}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400404 } else if len(meterConfig.Bands) < MaxMeterBand {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000405 logger.Errorw("Invalid-number-of-bands-in-meter", log.Fields{"Bands": meterConfig.Bands, "MeterID": sq.meterID})
Thomas Lee S94109f12020-03-03 16:39:29 +0530406 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800407 "reason": "Invalid-number-of-bands-in-meter",
408 "meterband-count": len(meterConfig.Bands),
409 "metabands": meterConfig.Bands,
Girish Kumarf26e4882020-03-05 06:49:10 +0000410 "meter-id": sq.meterID}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400411 }
412 cir := meterConfig.Bands[0].Rate
413 cbs := meterConfig.Bands[0].BurstSize
414 eir := meterConfig.Bands[1].Rate
415 ebs := meterConfig.Bands[1].BurstSize
416 pir := cir + eir
417 pbs := cbs + ebs
418 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
419
Gamze Abakafee36392019-10-03 11:17:24 +0000420 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Manikkaraj kb1d51442019-07-23 10:41:02 -0400421
npujarec5762e2020-01-01 14:08:48 +0530422 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficShaping, TrafficSched); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000423 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 -0400424 }
425
salmansiddiqui7ac62132019-08-22 03:58:50 +0000426 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400427 * store the meter id on the KV store, for further reference.
428 */
npujarec5762e2020-01-01 14:08:48 +0530429 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 +0000430 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 -0400431 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000432 logger.Debugw("updated-meter-info into KV store successfully", log.Fields{"Direction": Direction,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400433 "Meter": meterConfig})
434 return nil
435}
436
npujarec5762e2020-01-01 14:08:48 +0530437func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficShaping *tp_pb.TrafficShapingInfo, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000438
439 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
440
441 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000442 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 +0000443 }
444
Girish Kumar2ad402b2020-03-20 19:45:12 +0000445 logger.Debugw("Sending Traffic scheduler create to device", log.Fields{"Direction": sq.direction, "TrafficScheds": TrafficSched})
npujarec5762e2020-01-01 14:08:48 +0530446 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000447 IntfId: sq.intfID, OnuId: sq.onuID,
448 UniId: sq.uniID, PortNo: sq.uniPort,
449 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000450 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000451 }
452
453 // On receiving the CreateTrafficQueues request, the driver should create corresponding
454 // downstream queues.
Girish Kumar2ad402b2020-03-20 19:45:12 +0000455 logger.Debugw("Sending Traffic Queues create to device", log.Fields{"Direction": sq.direction, "TrafficQueues": trafficQueues})
npujarec5762e2020-01-01 14:08:48 +0530456 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000457 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
458 UniId: sq.uniID, PortNo: sq.uniPort,
459 TrafficQueues: trafficQueues}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000460 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"TrafficQueues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000461 }
462
Esin Karamanccb714b2019-11-29 15:02:06 +0000463 if sq.direction == tp_pb.Direction_DOWNSTREAM {
464 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(sq.tpInst)
465 if len(multicastTrafficQueues) > 0 {
466 if _, present := f.interfaceToMcastQueueMap[sq.intfID]; !present {
467 //assumed that there is only one queue per PON for the multicast service
468 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
469 //just put it in interfaceToMcastQueueMap to use for building group members
470 multicastQueuePerPonPort := multicastTrafficQueues[0]
471 f.interfaceToMcastQueueMap[sq.intfID] = &queueInfoBrief{
472 gemPortID: multicastQueuePerPonPort.GemportId,
473 servicePriority: multicastQueuePerPonPort.Priority,
474 }
475 //also store the queue info in kv store
npujarec5762e2020-01-01 14:08:48 +0530476 f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID,
Esin Karamanccb714b2019-11-29 15:02:06 +0000477 multicastQueuePerPonPort.GemportId,
478 multicastQueuePerPonPort.Priority)
479 }
480 }
481 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000482 return nil
483}
484
salmansiddiqui7ac62132019-08-22 03:58:50 +0000485// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530486func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400487
488 var Direction string
489 var SchedCfg *tp_pb.SchedulerConfig
490 var err error
Girish Kumar2ad402b2020-03-20 19:45:12 +0000491 logger.Debugw("Removing schedulers and Queues in OLT", log.Fields{"Direction": sq.direction, "IntfID": sq.intfID,
Gamze Abakafee36392019-10-03 11:17:24 +0000492 "OnuID": sq.onuID, "UniID": sq.uniID, "UniPort": sq.uniPort})
493 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000494 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400495 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000496 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000497 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400498 Direction = "downstream"
499 }
500
Girish Kumar8f73fe02019-12-09 13:19:37 +0000501 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000502 return olterrors.NewErrNotFound("scheduler-config", log.Fields{"IntID": sq.intfID, "Direction": sq.direction}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000503 }
504
npujarec5762e2020-01-01 14:08:48 +0530505 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400506 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000507 return olterrors.NewErrNotFound("meter", log.Fields{"onuID": sq.onuID}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400508 }
509 if KVStoreMeter == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000510 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 -0400511 return nil
512 }
513 cir := KVStoreMeter.Bands[0].Rate
514 cbs := KVStoreMeter.Bands[0].BurstSize
515 eir := KVStoreMeter.Bands[1].Rate
516 ebs := KVStoreMeter.Bands[1].BurstSize
517 pir := cir + eir
518 pbs := cbs + ebs
519
520 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
521
Gamze Abakafee36392019-10-03 11:17:24 +0000522 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Girish Kumar8f73fe02019-12-09 13:19:37 +0000523
524 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
525 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000526 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 +0000527 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400528
npujarec5762e2020-01-01 14:08:48 +0530529 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000530 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
531 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400532 TrafficQueues: TrafficQueues}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000533 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
534 log.Fields{"intfID": sq.intfID, "TrafficQueues": TrafficQueues}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400535 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000536 logger.Debug("Removed traffic queues successfully")
npujarec5762e2020-01-01 14:08:48 +0530537 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000538 IntfId: sq.intfID, OnuId: sq.onuID,
539 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400540 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000541 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
542 log.Fields{"intfID": sq.intfID, "TrafficSchedulers": TrafficSched}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400543 }
544
Girish Kumar2ad402b2020-03-20 19:45:12 +0000545 logger.Debug("Removed traffic schedulers successfully")
salmansiddiqui7ac62132019-08-22 03:58:50 +0000546
547 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400548 * delete the meter id on the KV store.
549 */
npujarec5762e2020-01-01 14:08:48 +0530550 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400551 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000552 return olterrors.NewErrAdapter("unable-to-remove-meter", log.Fields{"onu": sq.onuID, "meter": KVStoreMeter.MeterId}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400553 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000554 logger.Debugw("Removed-meter-from-KV-store successfully", log.Fields{"MeterId": KVStoreMeter.MeterId, "dir": Direction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400555 return err
556}
557
Gamze Abakafee36392019-10-03 11:17:24 +0000558// This function allocates tconts and GEM ports for an ONU
npujarec5762e2020-01-01 14:08:48 +0530559func (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 +0000560 var allocIDs []uint32
561 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530562 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530563 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000564 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000565
npujarec5762e2020-01-01 14:08:48 +0530566 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
567 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400568
569 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530570
Girish Kumar2ad402b2020-03-20 19:45:12 +0000571 logger.Infow("creating-new-tcont-and-gem", log.Fields{"pon": intfID, "onu": onuID, "uni": uniID})
Girish Gowdra54934262019-11-13 14:19:55 +0530572
Manikkaraj kb1d51442019-07-23 10:41:02 -0400573 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530574 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000575 if techProfileInstance == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000576 logger.Infow("tp-instance-not-found--creating-new", log.Fields{"path": tpPath})
npujarec5762e2020-01-01 14:08:48 +0530577 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000578 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530579 // This should not happen, something wrong in KV backend transaction
Girish Kumar2ad402b2020-03-20 19:45:12 +0000580 logger.Errorw("tp-instance-create-failed", log.Fields{"error": err, "tpID": TpID})
Gamze Abakafee36392019-10-03 11:17:24 +0000581 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530582 }
npujarec5762e2020-01-01 14:08:48 +0530583 f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530584 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000585 logger.Debugw("Tech-profile-instance-already-exist-for-given port-name", log.Fields{"uni": uni})
Girish Gowdra3d633032019-12-10 16:37:05 +0530586 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530587 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400588 if UsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000589 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
590 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
npujarec5762e2020-01-01 14:08:48 +0530591 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000592 logger.Errorw("CreateSchedulerQueues Failed-upstream", log.Fields{"error": err, "meterID": UsMeterID})
Gamze Abakafee36392019-10-03 11:17:24 +0000593 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400594 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530595 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400596 if DsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000597 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
598 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
npujarec5762e2020-01-01 14:08:48 +0530599 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000600 logger.Errorw("CreateSchedulerQueues Failed-downstream", log.Fields{"error": err, "meterID": DsMeterID})
Gamze Abakafee36392019-10-03 11:17:24 +0000601 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400602 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530603 }
Gamze Abakafee36392019-10-03 11:17:24 +0000604
605 allocID := techProfileInstance.UsScheduler.AllocID
Gamze Abakafee36392019-10-03 11:17:24 +0000606 for _, gem := range techProfileInstance.UpstreamGemPortAttributeList {
Gamze Abakafee36392019-10-03 11:17:24 +0000607 gemPortIDs = append(gemPortIDs, gem.GemportID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400608 }
Gamze Abakafee36392019-10-03 11:17:24 +0000609
Girish Gowdra3d633032019-12-10 16:37:05 +0530610 if tpInstanceExists {
611 return allocID, gemPortIDs, techProfileInstance
612 }
613
614 allocIDs = appendUnique(allocIDs, allocID)
615 for _, gemPortID := range gemPortIDs {
616 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
617 }
618
Girish Kumar2ad402b2020-03-20 19:45:12 +0000619 logger.Debugw("Allocated Tcont and GEM ports", log.Fields{"allocIDs": allocIDs, "gemports": allgemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530620 // Send Tconts and GEM ports to KV store
npujarec5762e2020-01-01 14:08:48 +0530621 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000622 return allocID, gemPortIDs, techProfileInstance
manikkaraj kbf256be2019-03-25 00:13:48 +0530623}
624
npujarec5762e2020-01-01 14:08:48 +0530625func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530626
Girish Kumar2ad402b2020-03-20 19:45:12 +0000627 logger.Debugw("Storing allocated Tconts and GEM ports into KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700628 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "allocID": allocID, "gemPortIDs": gemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530629 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530630 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000631 logger.Error("Errow while uploading allocID to KV store")
manikkaraj kbf256be2019-03-25 00:13:48 +0530632 }
npujarec5762e2020-01-01 14:08:48 +0530633 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000634 logger.Error("Errow while uploading GEMports to KV store")
manikkaraj kbf256be2019-03-25 00:13:48 +0530635 }
npujarec5762e2020-01-01 14:08:48 +0530636 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000637 logger.Error("Errow while uploading gemtopon map to KV store")
manikkaraj kbf256be2019-03-25 00:13:48 +0530638 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000639 logger.Debug("Stored tconts and GEM into KV store successfully")
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400640 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530641 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400642 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530643}
644
645func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000646 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530647 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000648 for _, intfID := range techRange.IntfIds {
649 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400650 tpCount++
Girish Kumar2ad402b2020-03-20 19:45:12 +0000651 logger.Debugw("Init tech profile done", log.Fields{"intfID": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530652 }
653 }
654 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400655 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530656 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800657 "reason": "TP count does not match number of PON ports",
658 "tech-profile-count": tpCount,
Girish Kumarf26e4882020-03-05 06:49:10 +0000659 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts()}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530660 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000661 logger.Infow("Populated techprofile for ponports successfully",
Manikkaraj kb1d51442019-07-23 10:41:02 -0400662 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
manikkaraj kbf256be2019-03-25 00:13:48 +0530663 return nil
664}
665
npujarec5762e2020-01-01 14:08:48 +0530666func (f *OpenOltFlowMgr) addUpstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530667 portNo uint32, uplinkClassifier map[string]interface{},
668 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800669 allocID uint32, gemportID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700670 uplinkClassifier[PacketTagType] = SingleTag
Girish Kumar2ad402b2020-03-20 19:45:12 +0000671 logger.Debugw("Adding upstream data flow", log.Fields{"uplinkClassifier": uplinkClassifier, "uplinkAction": uplinkAction})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800672 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700673 Upstream, logicalFlow, allocID, gemportID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530674 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530675}
676
npujarec5762e2020-01-01 14:08:48 +0530677func (f *OpenOltFlowMgr) addDownstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530678 portNo uint32, downlinkClassifier map[string]interface{},
679 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800680 allocID uint32, gemportID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700681 downlinkClassifier[PacketTagType] = DoubleTag
Girish Kumar2ad402b2020-03-20 19:45:12 +0000682 logger.Debugw("Adding downstream data flow", log.Fields{"downlinkClassifier": downlinkClassifier,
Manikkaraj k884c1242019-04-11 16:26:42 +0530683 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400684 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
685 if vlan, exists := downlinkClassifier[VlanVid]; exists {
686 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700687 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Manikkaraj kb1d51442019-07-23 10:41:02 -0400688 if uint32(metadata.(uint64)) == MkUniPortNum(intfID, onuID, uniID) {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000689 logger.Infow("Ignoring DL trap device flow from core", log.Fields{"flow": logicalFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800690 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400691 }
692 }
693 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530694 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400695
Manikkaraj k884c1242019-04-11 16:26:42 +0530696 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700697 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400698 // vlan_vid is a uint32. must be type asserted as such or conversion fails
699 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530700 if ok {
701 downlinkAction[VlanVid] = dlClVid & 0xfff
702 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530703 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800704 "reason": "failed to convert VLANID classifier",
705 "vlan-id": VlanVid}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530706 }
707
David K. Bainbridge794735f2020-02-11 21:01:37 -0800708 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700709 Downstream, logicalFlow, allocID, gemportID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530710}
711
npujarec5762e2020-01-01 14:08:48 +0530712func (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 +0530713 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800714 allocID uint32, gemPortID uint32) error {
Manikkaraj k884c1242019-04-11 16:26:42 +0530715 /* One of the OLT platform (Broadcom BAL) requires that symmetric
716 flows require the same flow_id to be used across UL and DL.
717 Since HSIA flow is the only symmetric flow currently, we need to
718 re-use the flow_id across both direction. The 'flow_category'
719 takes priority over flow_cookie to find any available HSIA_FLOW
720 id for the ONU.
721 */
Girish Kumar2ad402b2020-03-20 19:45:12 +0000722 logger.Debugw("Adding HSIA flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "classifier": classifier,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700723 "action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530724 "logicalFlow": *logicalFlow})
Girish Gowdrafae935c2020-02-17 19:21:44 +0530725 var vlanPbit uint32 = 0xff // means no pbit
Manikkaraj kb1d51442019-07-23 10:41:02 -0400726 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000727 vlanPbit = classifier[VlanPcp].(uint32)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000728 logger.Debugw("Found pbit in the flow", log.Fields{"VlanPbit": vlanPbit})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800729 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000730 logger.Debugw("pbit-not-found-in-flow", log.Fields{"vlan-pcp": VlanPcp})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400731 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700732 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530733 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000734 logger.Debug("flow-already-exists")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800735 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530736 }
npujarec5762e2020-01-01 14:08:48 +0530737 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530738 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530739 return olterrors.NewErrNotFound("hsia-flow-id", log.Fields{"direction": direction}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530740 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800741 classifierProto, err := makeOpenOltClassifierField(classifier)
742 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530743 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530744 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000745 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800746 actionProto, err := makeOpenOltActionField(action)
747 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530748 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530749 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000750 logger.Debugw("Created action proto", log.Fields{"action": *actionProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800751 networkIntfID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530752 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530753 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800754 log.Fields{
755 "classifier": classifier,
756 "action": action,
757 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530758 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700759 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
760 OnuId: int32(onuID),
761 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000762 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530763 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700764 AllocId: int32(allocID),
765 NetworkIntfId: int32(networkIntfID),
766 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530767 Classifier: classifierProto,
768 Action: actionProto,
769 Priority: int32(logicalFlow.Priority),
770 Cookie: logicalFlow.Cookie,
771 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800772 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530773 return olterrors.NewErrFlowOp("add", flowID, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530774 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000775 logger.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800776 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
777 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
778 flow.OnuId,
779 flow.UniId,
780 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530781 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": flow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800782 }
783 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +0530784}
Esin Karamanae41e2b2019-12-17 18:13:13 +0000785
David K. Bainbridge794735f2020-02-11 21:01:37 -0800786func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32) error {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530787
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530788 networkIntfID, err := getNniIntfID(classifier, action)
789 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530790 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800791 "classifier": classifier,
792 "action": action},
793 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530794 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530795
796 // Clear the action map
797 for k := range action {
798 delete(action, k)
799 }
800
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700801 action[TrapToHost] = true
802 classifier[UDPSrc] = uint32(68)
803 classifier[UDPDst] = uint32(67)
804 classifier[PacketTagType] = SingleTag
805 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530806
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700807 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530808 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000809 logger.Debug("Flow-exists--not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800810 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530811 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530812
David K. Bainbridge794735f2020-02-11 21:01:37 -0800813 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 +0530814
815 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530816 return olterrors.NewErrNotFound("flow", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800817 "interface-id": intfID,
818 "gem-port": gemPortID,
819 "cookie": flowStoreCookie},
820 err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530821 }
822
Girish Kumar2ad402b2020-03-20 19:45:12 +0000823 logger.Debugw("Creating UL DHCP flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530824
David K. Bainbridge794735f2020-02-11 21:01:37 -0800825 classifierProto, err := makeOpenOltClassifierField(classifier)
826 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530827 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530828 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000829 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800830 actionProto, err := makeOpenOltActionField(action)
831 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530832 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530833 }
834
David K. Bainbridge794735f2020-02-11 21:01:37 -0800835 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700836 OnuId: int32(onuID),
837 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530838 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700839 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700840 AllocId: int32(allocID),
841 NetworkIntfId: int32(networkIntfID),
842 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530843 Classifier: classifierProto,
844 Action: actionProto,
845 Priority: int32(logicalFlow.Priority),
846 Cookie: logicalFlow.Cookie,
847 PortNo: portNo}
848
David K. Bainbridge794735f2020-02-11 21:01:37 -0800849 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530850 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800851 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000852 logger.Debug("DHCP UL flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800853 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
854 if err := f.updateFlowInfoToKVStore(ctx, dhcpFlow.AccessIntfId,
855 dhcpFlow.OnuId,
856 dhcpFlow.UniId,
857 dhcpFlow.FlowId, flowsToKVStore); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530858 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId, log.Fields{"flow": dhcpFlow}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530859 }
860
David K. Bainbridge794735f2020-02-11 21:01:37 -0800861 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530862}
863
Esin Karamanae41e2b2019-12-17 18:13:13 +0000864//addIGMPTrapFlow creates IGMP trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +0530865func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
David K. Bainbridge794735f2020-02-11 21:01:37 -0800866 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32) error {
867 return f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, IgmpFlow)
Esin Karamanae41e2b2019-12-17 18:13:13 +0000868}
869
870//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +0530871func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
David K. Bainbridge794735f2020-02-11 21:01:37 -0800872 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, flowType string) error {
Esin Karamanae41e2b2019-12-17 18:13:13 +0000873
874 networkIntfID, err := getNniIntfID(classifier, action)
875 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530876 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800877 "classifier": classifier,
878 "action": action},
879 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000880 }
881
882 // Clear the action map
883 for k := range action {
884 delete(action, k)
885 }
886
887 action[TrapToHost] = true
888 classifier[PacketTagType] = SingleTag
889 delete(classifier, VlanVid)
890
891 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530892 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkIntfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000893 logger.Debug("Flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800894 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +0000895 }
896
npujarec5762e2020-01-01 14:08:48 +0530897 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 +0000898
899 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530900 return olterrors.NewErrNotFound("flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800901 "interface-id": intfID,
902 "oni-id": onuID,
903 "cookie": flowStoreCookie,
904 "flow-type": flowType},
905 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000906 }
907
Girish Kumar2ad402b2020-03-20 19:45:12 +0000908 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 +0000909
David K. Bainbridge794735f2020-02-11 21:01:37 -0800910 classifierProto, err := makeOpenOltClassifierField(classifier)
911 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530912 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000913 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000914 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800915 actionProto, err := makeOpenOltActionField(action)
916 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530917 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000918 }
919
David K. Bainbridge794735f2020-02-11 21:01:37 -0800920 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +0000921 OnuId: int32(onuID),
922 UniId: int32(uniID),
923 FlowId: flowID,
924 FlowType: Upstream,
925 AllocId: int32(allocID),
926 NetworkIntfId: int32(networkIntfID),
927 GemportId: int32(gemPortID),
928 Classifier: classifierProto,
929 Action: actionProto,
930 Priority: int32(logicalFlow.Priority),
931 Cookie: logicalFlow.Cookie,
932 PortNo: portNo}
933
David K. Bainbridge794735f2020-02-11 21:01:37 -0800934 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530935 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": flow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800936 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000937 logger.Debugf("%s UL flow added to device successfully", flowType)
Esin Karamanae41e2b2019-12-17 18:13:13 +0000938
David K. Bainbridge794735f2020-02-11 21:01:37 -0800939 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, flowType, flowID, logicalFlow.Id)
940 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
941 flow.OnuId,
942 flow.UniId,
943 flow.FlowId, flowsToKVStore); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530944 return olterrors.NewErrPersistence("update", "flow", flow.FlowId, log.Fields{"flow": flow}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000945 }
946
David K. Bainbridge794735f2020-02-11 21:01:37 -0800947 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +0000948}
949
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700950// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Girish Gowdrafae935c2020-02-17 19:21:44 +0530951func (f *OpenOltFlowMgr) addEAPOLFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, vlanID uint32) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000952 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 +0530953
954 uplinkClassifier := make(map[string]interface{})
955 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +0530956
manikkaraj kbf256be2019-03-25 00:13:48 +0530957 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700958 uplinkClassifier[EthType] = uint32(EapEthType)
959 uplinkClassifier[PacketTagType] = SingleTag
960 uplinkClassifier[VlanVid] = vlanID
manikkaraj kbf256be2019-03-25 00:13:48 +0530961 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700962 uplinkAction[TrapToHost] = true
963 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530964 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000965 logger.Debug("Flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800966 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530967 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530968 //Add Uplink EAPOL Flow
npujarec5762e2020-01-01 14:08:48 +0530969 uplinkFlowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530970 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530971 return olterrors.NewErrNotFound("flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800972 "interface-id": intfID,
973 "onu-id": onuID,
974 "coookie": flowStoreCookie},
975 err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +0530976 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000977 logger.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530978
David K. Bainbridge794735f2020-02-11 21:01:37 -0800979 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
980 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530981 return olterrors.NewErrInvalidValue(log.Fields{"classifier": uplinkClassifier}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +0530982 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000983 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800984 actionProto, err := makeOpenOltActionField(uplinkAction)
985 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530986 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +0530987 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000988 logger.Debugw("Created action proto", log.Fields{"action": *actionProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800989 networkIntfID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530990 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530991 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800992 "classifier": classifier,
993 "action": action},
994 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530995 }
996
David K. Bainbridge794735f2020-02-11 21:01:37 -0800997 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700998 OnuId: int32(onuID),
999 UniId: int32(uniID),
1000 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001001 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001002 AllocId: int32(allocID),
1003 NetworkIntfId: int32(networkIntfID),
1004 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301005 Classifier: classifierProto,
1006 Action: actionProto,
1007 Priority: int32(logicalFlow.Priority),
1008 Cookie: logicalFlow.Cookie,
1009 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001010 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301011 return olterrors.NewErrFlowOp("add", uplinkFlowID, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001012 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001013 logger.Debug("EAPOL UL flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001014 flowCategory := "EAPOL"
1015 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
1016 if err := f.updateFlowInfoToKVStore(ctx, upstreamFlow.AccessIntfId,
1017 upstreamFlow.OnuId,
1018 upstreamFlow.UniId,
1019 upstreamFlow.FlowId,
1020 /* lowCategory, */
1021 flowsToKVStore); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301022 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId, log.Fields{"flow": upstreamFlow}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301023 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301024
Girish Kumar2ad402b2020-03-20 19:45:12 +00001025 logger.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001026 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301027}
1028
David K. Bainbridge794735f2020-02-11 21:01:37 -08001029func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001030 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001031
1032 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1033 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1034 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001035 if vlanID != ReservedVlan {
1036 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001037 classifier.OVid = vid
1038 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301039 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001040 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1041 vid := uint32(metadata)
1042 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001043 classifier.IVid = vid
1044 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301045 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301046 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001047 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301048 classifier.OPbits = vlanPcp
1049 } else {
1050 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301051 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001052 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1053 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1054 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1055 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001056 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001057 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1058 classifier.PktTagType = pktTagType
1059
1060 switch pktTagType {
1061 case SingleTag:
1062 case DoubleTag:
1063 case Untagged:
1064 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001065 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301066 }
1067 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001068 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301069}
1070
David K. Bainbridge794735f2020-02-11 21:01:37 -08001071func makeOpenOltActionField(actionInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001072 var actionCmd openoltpb2.ActionCmd
1073 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301074 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001075 if _, ok := actionInfo[PopVlan]; ok {
1076 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301077 action.Cmd.RemoveOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001078 } else if _, ok := actionInfo[PushVlan]; ok {
1079 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301080 action.Cmd.AddOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001081 } else if _, ok := actionInfo[TrapToHost]; ok {
1082 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301083 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001084 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301085 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001086 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301087}
1088
Manikkaraj kb1d51442019-07-23 10:41:02 -04001089func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uni string, TpID uint32) string {
1090 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +05301091}
1092
Gamze Abakafee36392019-10-03 11:17:24 +00001093// DeleteTechProfileInstances removes the tech profile instances from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301094func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, sn string) error {
1095 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001096 uniPortName := fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001097 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301098 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001099 olterrors.NewErrAdapter("delete-tech-profile-failed", nil, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301100 // return err
1101 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001102 }
1103 }
1104 return nil
1105}
1106
1107// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301108func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001109 if uniPortName == "" {
1110 uniPortName = fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1111 }
npujarec5762e2020-01-01 14:08:48 +05301112 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001113 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 -04001114 }
1115 return nil
1116}
1117
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001118func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +05301119 if len(classifier) == 0 { // should never happen
Girish Kumar2ad402b2020-03-20 19:45:12 +00001120 logger.Error("Invalid classfier object")
manikkaraj kbf256be2019-03-25 00:13:48 +05301121 return 0
1122 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001123 logger.Debugw("generating flow store cookie", log.Fields{"classifier": classifier, "gemPortID": gemPortID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301124 var jsonData []byte
1125 var flowString string
1126 var err error
1127 // TODO: Do we need to marshall ??
1128 if jsonData, err = json.Marshal(classifier); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001129 logger.Error("Failed to encode classifier")
manikkaraj kbf256be2019-03-25 00:13:48 +05301130 return 0
1131 }
1132 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001133 if gemPortID != 0 {
1134 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +05301135 }
1136 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001137 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +05301138 hash := big.NewInt(0)
1139 hash.SetBytes(h.Sum(nil))
Girish Gowdra3d633032019-12-10 16:37:05 +05301140 generatedHash := hash.Uint64()
Girish Kumar2ad402b2020-03-20 19:45:12 +00001141 logger.Debugw("hash generated", log.Fields{"hash": generatedHash})
Girish Gowdra3d633032019-12-10 16:37:05 +05301142 return generatedHash
manikkaraj kbf256be2019-03-25 00:13:48 +05301143}
1144
npujarec5762e2020-01-01 14:08:48 +05301145func (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 +05301146 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001147 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001148 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1149 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1150 */
1151 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001152 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001153 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001154 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001155 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001156 // Get existing flows matching flowid for given subscriber from KV store
npujarec5762e2020-01-01 14:08:48 +05301157 existingFlows := f.resourceMgr.GetFlowIDInfo(ctx, intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001158 if existingFlows != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001159 logger.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001160 //for _, f := range *existingFlows {
1161 // flows = append(flows, f)
1162 //}
1163 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001164 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001165 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 +05301166 return &flows
1167}
1168
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001169//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
1170// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
1171// var intfId uint32
1172// /* For flows which trap out of the NNI, the AccessIntfId is invalid
1173// (set to -1). In such cases, we need to refer to the NetworkIntfId .
1174// */
1175// if flow.AccessIntfId != -1 {
1176// intfId = uint32(flow.AccessIntfId)
1177// } else {
1178// intfId = uint32(flow.NetworkIntfId)
1179// }
1180// // Get existing flows matching flowid for given subscriber from KV store
1181// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
1182// if existingFlows != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001183// logger.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001184// for _, f := range *existingFlows {
1185// flows = append(flows, f)
1186// }
1187// }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001188// 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 -04001189// return &flows
1190//}
1191
npujarec5762e2020-01-01 14:08:48 +05301192func (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 +00001193 logger.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
npujarec5762e2020-01-01 14:08:48 +05301194 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, intfID, onuID, uniID, flowID, flows); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001195 logger.Debug("Error while Storing flow into KV store")
manikkaraj k17652a72019-05-06 09:06:36 -04001196 return err
1197 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001198 logger.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +05301199 return nil
1200}
1201
David K. Bainbridge794735f2020-02-11 21:01:37 -08001202func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001203
1204 var intfID uint32
1205 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1206 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1207 */
1208 if deviceFlow.AccessIntfId != -1 {
1209 intfID = uint32(deviceFlow.AccessIntfId)
1210 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001211 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001212 intfID = uint32(deviceFlow.NetworkIntfId)
1213 }
1214
Girish Kumar2ad402b2020-03-20 19:45:12 +00001215 logger.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301216 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001217
1218 st, _ := status.FromError(err)
1219 if st.Code() == codes.AlreadyExists {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001220 logger.Debug("Flow already exists", log.Fields{"err": err, "deviceFlow": deviceFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001221 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301222 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001223
1224 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001225 logger.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": deviceFlow})
npujarec5762e2020-01-01 14:08:48 +05301226 f.resourceMgr.FreeFlowID(ctx, intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001227 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001228 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301229 if deviceFlow.GemportId != -1 {
1230 // No need to register the flow if it is a trap on nni flow.
npujarec5762e2020-01-01 14:08:48 +05301231 f.registerFlow(ctx, logicalFlow, deviceFlow)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301232 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001233 logger.Debugw("Flow added to device successfully ", log.Fields{"flow": *deviceFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001234 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001235}
1236
David K. Bainbridge794735f2020-02-11 21:01:37 -08001237func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001238 logger.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001239 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1240 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001241 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001242 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 -07001243 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001244 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001245 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001246 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001247
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001248 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001249 logger.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001250 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301251}
1252
1253/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1254 //update core flows_proxy : flows_proxy.update('/', flows)
1255}
1256
1257func generateStoredId(flowId uint32, direction string)uint32{
1258
David K. Bainbridge82efc492019-09-04 09:57:11 -07001259 if direction == Upstream{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001260 logger.Debug("Upstream flow shifting flowid")
manikkaraj kbf256be2019-03-25 00:13:48 +05301261 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001262 }else if direction == Downstream{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001263 logger.Debug("Downstream flow not shifting flowid")
manikkaraj kbf256be2019-03-25 00:13:48 +05301264 return flowId
1265 }else{
Girish Kumar2ad402b2020-03-20 19:45:12 +00001266 logger.Errorw("Unrecognized direction",log.Fields{"direction": direction})
manikkaraj kbf256be2019-03-25 00:13:48 +05301267 return flowId
1268 }
1269}
1270
1271*/
1272
David K. Bainbridge794735f2020-02-11 21:01:37 -08001273func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001274
1275 classifierInfo := make(map[string]interface{})
1276 actionInfo := make(map[string]interface{})
1277
1278 classifierInfo[EthType] = uint32(LldpEthType)
1279 classifierInfo[PacketTagType] = Untagged
1280 actionInfo[TrapToHost] = true
1281
1282 // LLDP flow is installed to trap LLDP packets on the NNI port.
1283 // We manage flow_id resource pool on per PON port basis.
1284 // Since this situation is tricky, as a hack, we pass the NNI port
1285 // index (network_intf_id) as PON port Index for the flow_id resource
1286 // pool. Also, there is no ONU Id available for trapping LLDP packets
1287 // on NNI port, use onu_id as -1 (invalid)
1288 // ****************** CAVEAT *******************
1289 // This logic works if the NNI Port Id falls within the same valid
1290 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1291 // we need to have a re-look at this.
1292 // *********************************************
1293
1294 var onuID = -1
1295 var uniID = -1
1296 var gemPortID = -1
1297
David K. Bainbridge794735f2020-02-11 21:01:37 -08001298 networkInterfaceID, err := IntfIDFromNniPortNum(portNo)
1299 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301300 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001301 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001302 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05301303 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001304 logger.Debug("Flow-exists--not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001305 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001306 }
npujarec5762e2020-01-01 14:08:48 +05301307 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001308
1309 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301310 return olterrors.NewErrNotFound("flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001311 "interface-id": networkInterfaceID,
1312 "onu-id": onuID,
1313 "uni-id": uniID,
1314 "gem-port-id": gemPortID,
1315 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00001316 err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001317 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001318 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1319 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001320 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001321 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001322 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001323 actionProto, err := makeOpenOltActionField(actionInfo)
1324 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001325 return olterrors.NewErrInvalidValue(log.Fields{"action": actionInfo}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001326 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001327 logger.Debugw("Created action proto", log.Fields{"action": *actionProto})
Humera Kouser94d7a842019-08-25 19:04:32 -04001328
1329 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1330 OnuId: int32(onuID), // OnuId not required
1331 UniId: int32(uniID), // UniId not used
1332 FlowId: flowID,
1333 FlowType: Downstream,
1334 NetworkIntfId: int32(networkInterfaceID),
1335 GemportId: int32(gemPortID),
1336 Classifier: classifierProto,
1337 Action: actionProto,
1338 Priority: int32(flow.Priority),
1339 Cookie: flow.Cookie,
1340 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001341 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001342 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001343 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001344 logger.Debug("LLDP trap on NNI flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001345 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, flow.Id)
1346 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
1347 int32(onuID),
1348 int32(uniID),
1349 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001350 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001351 }
1352 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301353}
1354
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301355func getUniPortPath(intfID uint32, onuID int32, uniID int32) string {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001356 return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1357}
1358
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001359//getOnuDevice to fetch onu from cache or core.
1360func (f *OpenOltFlowMgr) getOnuDevice(intfID uint32, onuID uint32) (*OnuDevice, error) {
1361 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1362 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1363 if !ok {
1364 logger.Debugw("couldnt-find-onu-in-cache", log.Fields{"intfID": intfID, "onuID": onuID})
1365 onuDevice, err := f.getChildDevice(intfID, onuID)
1366 if err != nil {
1367 return nil, olterrors.NewErrNotFound("onu-child-device", log.Fields{"onuId": onuID, "intfID": intfID}, err)
1368 }
1369 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1370 //better to ad the device to cache here.
1371 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1372 } else {
1373 logger.Debugw("Found-onu-in-cache", log.Fields{"intfID": intfID, "onuID": onuID})
1374 }
1375
1376 return onuDev.(*OnuDevice), nil
1377}
1378
1379//getChildDevice to fetch onu
1380func (f *OpenOltFlowMgr) getChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001381 logger.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001382 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001383 onuDevice, err := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
1384 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301385 return nil, olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001386 "interface-id": parentPortNo,
1387 "onu-id": onuID},
Girish Kumarf26e4882020-03-05 06:49:10 +00001388 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301389 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001390 logger.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
Manikkaraj k884c1242019-04-11 16:26:42 +05301391 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301392}
1393
1394func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001395 logger.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301396 return nil
1397}
1398
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001399func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001400 logger.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301401}
1402
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001403func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001404 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001405 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001406 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001407 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001408}
1409
Girish Gowdra6b130582019-11-20 16:45:20 +05301410func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001411 onuDev, err := f.getOnuDevice(intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301412 if err != nil {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001413 logger.Debugw("couldnt-find-onu-child-device", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1414 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301415 }
1416
1417 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001418 logger.Debugw("sending gem port delete to openonu adapter", log.Fields{"msg": *delGemPortMsg})
Girish Gowdra6b130582019-11-20 16:45:20 +05301419 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1420 delGemPortMsg,
1421 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
1422 f.deviceHandler.deviceType,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001423 onuDev.deviceType,
1424 onuDev.deviceID,
1425 onuDev.proxyDeviceID, ""); sendErr != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001426 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001427 "toAdapter": onuDev.deviceType, "onuId": onuDev.deviceID,
1428 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301429 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001430 logger.Debugw("success sending del gem port to onu adapter", log.Fields{"msg": delGemPortMsg})
Girish Gowdra6b130582019-11-20 16:45:20 +05301431 return nil
1432}
1433
1434func (f *OpenOltFlowMgr) sendDeleteTcontToChild(intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001435 onuDev, err := f.getOnuDevice(intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301436 if err != nil {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001437 logger.Debugw("couldnt-find-onu-child-device", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1438 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301439 }
1440
1441 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001442 logger.Debugw("sending tcont delete to openonu adapter", log.Fields{"msg": *delTcontMsg})
Girish Gowdra6b130582019-11-20 16:45:20 +05301443 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1444 delTcontMsg,
1445 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
1446 f.deviceHandler.deviceType,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001447 onuDev.deviceType,
1448 onuDev.deviceID,
1449 onuDev.proxyDeviceID, ""); sendErr != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001450 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001451 "toAdapter": onuDev.deviceType, "onuId": onuDev.deviceID,
1452 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301453 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001454 logger.Debugw("success sending del tcont to onu adapter", log.Fields{"msg": delTcontMsg})
Girish Gowdra6b130582019-11-20 16:45:20 +05301455 return nil
1456}
1457
Girish Gowdra3d633032019-12-10 16:37:05 +05301458func (f *OpenOltFlowMgr) deletePendingFlows(Intf uint32, onuID int32, uniID int32) {
1459 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1460 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); ok {
1461 if val.(int) > 0 {
1462 pnFlDels := val.(int) - 1
1463 if pnFlDels > 0 {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001464 logger.Debugw("flow delete succeeded, more pending",
Girish Gowdra3d633032019-12-10 16:37:05 +05301465 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID, "currPendingFlowCnt": pnFlDels})
1466 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1467 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001468 logger.Debugw("all pending flow deletes handled, removing entry from map",
Girish Gowdra3d633032019-12-10 16:37:05 +05301469 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1470 f.pendingFlowDelete.Delete(pnFlDelKey)
1471 }
1472 }
1473 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001474 logger.Debugw("no pending delete flows found",
Girish Gowdra3d633032019-12-10 16:37:05 +05301475 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1476
1477 }
1478
1479}
1480
Girish Gowdrac3037402020-01-22 20:29:53 +05301481// Once the gemport is released for a given onu, it also has to be cleared from local cache
1482// which was used for deriving the gemport->logicalPortNo during packet-in.
1483// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1484// is conveyed to ONOS during packet-in OF message.
1485func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(intfID uint32, onuID uint32, gemPortID uint32) {
1486 f.lockCache.Lock()
1487 defer f.lockCache.Unlock()
1488 onugem := f.onuGemInfo[intfID]
serkant.uluderya96af4932020-02-20 16:58:48 -08001489 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301490 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001491 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301492 // If the gemport is found, delete it from local cache.
1493 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001494 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1495 onugem[i] = onu
Girish Kumar2ad402b2020-03-20 19:45:12 +00001496 logger.Debugw("removed gemport from local cache",
serkant.uluderya96af4932020-02-20 16:58:48 -08001497 log.Fields{"intfID": intfID, "onuID": onuID, "deletedGemPortID": gemPortID, "gemPorts": onu.GemPorts})
Girish Gowdrac3037402020-01-22 20:29:53 +05301498 break
1499 }
1500 }
1501 break
1502 }
1503 }
1504}
1505
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301506//clearResources clears pon resources in kv store and the device
npujarec5762e2020-01-01 14:08:48 +05301507func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301508 gemPortID int32, flowID uint32, flowDirection string,
1509 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001510
Chaitrashree G S90a17952019-11-14 21:51:21 -05001511 tpID, err := getTpIDFromFlow(flow)
1512 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001513 return olterrors.NewErrNotFound("tpid", log.Fields{"flow": flow, "pon": Intf, "onuID": onuID, "uniID": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001514 }
Gamze Abakafee36392019-10-03 11:17:24 +00001515
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001516 if len(updatedFlows) >= 0 {
1517 // There are still flows referencing the same flow_id.
1518 // So the flow should not be freed yet.
1519 // For ex: Case of HSIA where same flow is shared
1520 // between DS and US.
Girish Kumarf26e4882020-03-05 06:49:10 +00001521 if err := f.updateFlowInfoToKVStore(ctx, int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows); err != nil {
1522 olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": updatedFlows}, err).Log()
1523 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001524 if len(updatedFlows) == 0 {
Girish Gowdra3d633032019-12-10 16:37:05 +05301525 // Do this for subscriber flows only (not trap from NNI flows)
1526 if onuID != -1 && uniID != -1 {
1527 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1528 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001529 logger.Debugw("creating entry for pending flow delete",
Girish Gowdra3d633032019-12-10 16:37:05 +05301530 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1531 f.pendingFlowDelete.Store(pnFlDelKey, 1)
1532 } else {
1533 pnFlDels := val.(int) + 1
Girish Kumar2ad402b2020-03-20 19:45:12 +00001534 logger.Debugw("updating flow delete entry",
Girish Gowdra3d633032019-12-10 16:37:05 +05301535 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID, "currPendingFlowCnt": pnFlDels})
1536 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1537 }
1538
1539 defer f.deletePendingFlows(Intf, onuID, uniID)
1540 }
1541
Girish Kumar2ad402b2020-03-20 19:45:12 +00001542 logger.Debugw("Releasing flow Id to resource manager", log.Fields{"Intf": Intf, "onuId": onuID, "uniId": uniID, "flowId": flowID})
npujarec5762e2020-01-01 14:08:48 +05301543 f.resourceMgr.FreeFlowID(ctx, Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001544
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301545 uni := getUniPortPath(Intf, onuID, uniID)
1546 tpPath := f.getTPpath(Intf, uni, tpID)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001547 logger.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
npujarec5762e2020-01-01 14:08:48 +05301548 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
Girish Kumarf26e4882020-03-05 06:49:10 +00001549 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1550 return olterrors.NewErrNotFound("tech-profile-in-kv-store", log.Fields{"tpID": tpID, "path": tpPath}, err)
Gamze Abakafee36392019-10-03 11:17:24 +00001551 }
1552
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301553 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00001554 if f.isGemPortUsedByAnotherFlow(gemPK) {
1555 flowIDs := f.flowsUsedByGemPort[gemPK]
1556 for i, flowIDinMap := range flowIDs {
1557 if flowIDinMap == flowID {
1558 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301559 // everytime flowsUsedByGemPort cache is updated the same should be updated
1560 // in kv store by calling UpdateFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001561 f.flowsUsedByGemPort[gemPK] = flowIDs
npujarec5762e2020-01-01 14:08:48 +05301562 f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs)
Gamze Abakafee36392019-10-03 11:17:24 +00001563 break
1564 }
1565 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001566 logger.Debugw("Gem port id is still used by other flows", log.Fields{"gemPortID": gemPortID, "usedByFlows": flowIDs})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301567 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00001568 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001569 logger.Debugf("Gem port id %d is not used by another flow - releasing the gem port", gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301570 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001571 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1572 // 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 +05301573 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
Girish Gowdrac3037402020-01-22 20:29:53 +05301574 f.deleteGemPortFromLocalCache(Intf, uint32(onuID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001575 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301576 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1577 // by calling DeleteFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001578 delete(f.flowsUsedByGemPort, gemPK)
npujarec5762e2020-01-01 14:08:48 +05301579 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
1580 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001581 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05301582 // Delete the gem port on the ONU.
1583 if err := f.sendDeleteGemPortToChild(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001584 logger.Errorw("error processing delete gem-port towards onu",
Girish Gowdra6b130582019-11-20 16:45:20 +05301585 log.Fields{"err": err, "pon": Intf, "onuID": onuID, "uniID": uniID, "gemPortId": gemPortID})
1586 }
Gamze Abakafee36392019-10-03 11:17:24 +00001587
npujarec5762e2020-01-01 14:08:48 +05301588 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001589 if !ok {
npujarec5762e2020-01-01 14:08:48 +05301590 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID)
1591 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1592 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1593 f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID)
1594 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301595 // Delete the TCONT on the ONU.
1596 if err := f.sendDeleteTcontToChild(Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001597 logger.Errorw("error processing delete tcont towards onu",
Girish Gowdra6b130582019-11-20 16:45:20 +05301598 log.Fields{"pon": Intf, "onuID": onuID, "uniID": uniID, "allocId": techprofileInst.UsScheduler.AllocID})
1599 }
Gamze Abakafee36392019-10-03 11:17:24 +00001600 }
1601 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001602 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301603 return nil
1604}
1605
David K. Bainbridge794735f2020-02-11 21:01:37 -08001606// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05301607func (f *OpenOltFlowMgr) clearFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) {
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301608
Girish Kumar2ad402b2020-03-20 19:45:12 +00001609 logger.Debugw("clearFlowFromResourceManager", log.Fields{"flowDirection": flowDirection, "flow": *flow})
Esin Karamanccb714b2019-11-29 15:02:06 +00001610
1611 if flowDirection == Multicast {
npujarec5762e2020-01-01 14:08:48 +05301612 f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00001613 return
1614 }
1615
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301616 var updatedFlows []rsrcMgr.FlowInfo
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301617 classifierInfo := make(map[string]interface{})
1618
1619 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
1620 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001621 logger.Error(err)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301622 return
1623 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301624
David K. Bainbridge794735f2020-02-11 21:01:37 -08001625 onuID := int32(onu)
1626 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301627
1628 for _, field := range flows.GetOfbFields(flow) {
1629 if field.Type == flows.IP_PROTO {
1630 classifierInfo[IPProto] = field.GetIpProto()
Girish Kumar2ad402b2020-03-20 19:45:12 +00001631 logger.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301632 }
1633 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001634 logger.Debugw("Extracted access info from flow to be deleted",
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301635 log.Fields{"ponIntf": Intf, "onuID": onuID, "uniID": uniID})
1636
1637 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1638 onuID = -1
1639 uniID = -1
Girish Kumar2ad402b2020-03-20 19:45:12 +00001640 logger.Debug("Trap on nni flow set oni, uni to -1")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001641 Intf, err = IntfIDFromNniPortNum(inPort)
1642 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001643 logger.Errorw("invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001644 log.Fields{
1645 "port-number": inPort,
1646 "error": err})
1647 return
1648 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301649 }
npujarec5762e2020-01-01 14:08:48 +05301650 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, Intf, onuID, uniID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001651 for _, flowID := range flowIds {
npujarec5762e2020-01-01 14:08:48 +05301652 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flowID)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301653 if flowInfo == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001654 logger.Debugw("No FlowInfo found found in KV store",
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301655 log.Fields{"Intf": Intf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1656 return
1657 }
1658 updatedFlows = nil
1659 for _, flow := range *flowInfo {
1660 updatedFlows = append(updatedFlows, flow)
1661 }
1662
1663 for i, storedFlow := range updatedFlows {
1664 if flow.Id == storedFlow.LogicalFlowID {
1665 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001666 logger.Debugw("Flow to be deleted", log.Fields{"flow": storedFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001667 // DKB
1668 if err = f.removeFlowFromDevice(&removeFlowMessage); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001669 logger.Errorw("failed-to-remove-flow", log.Fields{"error": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001670 return
1671 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001672 logger.Debug("Flow removed from device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001673 //Remove the Flow from FlowInfo
1674 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1675 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
1676 flowID, flowDirection, portNum, updatedFlows); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001677 logger.Error("Failed to clear resources for flow", log.Fields{"flow": storedFlow})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301678 return
1679 }
1680 }
1681 }
1682 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001683}
1684
Esin Karamanccb714b2019-11-29 15:02:06 +00001685//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
1686// clears resources reserved for this multicast flow
npujarec5762e2020-01-01 14:08:48 +05301687func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) {
Esin Karamanccb714b2019-11-29 15:02:06 +00001688 classifierInfo := make(map[string]interface{})
1689 formulateClassifierInfoFromFlow(classifierInfo, flow)
Esin Karaman65409d82020-03-18 10:58:18 +00001690 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00001691
1692 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001693 logger.Warnw("No inPort found. Cannot release resources of the multicast flow.", log.Fields{"flowId:": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001694 return
1695 }
1696
Esin Karamanccb714b2019-11-29 15:02:06 +00001697 var onuID = int32(NoneOnuID)
1698 var uniID = int32(NoneUniID)
1699 var flowID uint32
1700 var updatedFlows []rsrcMgr.FlowInfo
1701
npujarec5762e2020-01-01 14:08:48 +05301702 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, networkInterfaceID, onuID, uniID)
Esin Karamanccb714b2019-11-29 15:02:06 +00001703
1704 for _, flowID = range flowIds {
npujarec5762e2020-01-01 14:08:48 +05301705 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00001706 if flowInfo == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001707 logger.Debugw("No multicast FlowInfo found in the KV store",
Esin Karamanccb714b2019-11-29 15:02:06 +00001708 log.Fields{"Intf": networkInterfaceID, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1709 continue
1710 }
1711 updatedFlows = nil
1712 for _, flow := range *flowInfo {
1713 updatedFlows = append(updatedFlows, flow)
1714 }
1715 for i, storedFlow := range updatedFlows {
1716 if flow.Id == storedFlow.LogicalFlowID {
1717 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001718 logger.Debugw("Multicast flow to be deleted", log.Fields{"flow": storedFlow})
Esin Karamanccb714b2019-11-29 15:02:06 +00001719 //remove from device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001720 if err := f.removeFlowFromDevice(&removeFlowMessage); err != nil {
1721 // DKB
Girish Kumar2ad402b2020-03-20 19:45:12 +00001722 logger.Errorw("failed-to-remove-multicast-flow",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001723 log.Fields{
1724 "flow-id": flow.Id,
1725 "error": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00001726 return
1727 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001728 logger.Debugw("Multicast flow removed from device successfully", log.Fields{"flowId": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001729 //Remove the Flow from FlowInfo
1730 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
npujarec5762e2020-01-01 14:08:48 +05301731 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID), NoneOnuID, NoneUniID, flowID, &updatedFlows); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001732 logger.Error("Failed to delete multicast flow from the KV store", log.Fields{"flow": storedFlow, "err": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00001733 return
1734 }
1735 //release flow id
Girish Kumar2ad402b2020-03-20 19:45:12 +00001736 logger.Debugw("Releasing multicast flow id", log.Fields{"flowId": flowID, "interfaceID": networkInterfaceID})
npujarec5762e2020-01-01 14:08:48 +05301737 f.resourceMgr.FreeFlowID(ctx, uint32(networkInterfaceID), NoneOnuID, NoneUniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00001738 }
1739 }
1740 }
1741}
1742
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001743//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07001744func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001745 logger.Debugw("Removing Flow", log.Fields{"flow": flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301746 var direction string
1747 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001748
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301749 for _, action := range flows.GetActions(flow) {
1750 if action.Type == flows.OUTPUT {
1751 if out := action.GetOutput(); out != nil {
1752 actionInfo[Output] = out.GetPort()
Girish Kumar2ad402b2020-03-20 19:45:12 +00001753 logger.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301754 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001755 logger.Error("Invalid output port in action")
Girish Gowdracefae192020-03-19 18:14:10 -07001756 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001757 }
1758 }
1759 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001760
1761 if flows.HasGroup(flow) {
1762 direction = Multicast
Girish Gowdracefae192020-03-19 18:14:10 -07001763 f.clearFlowFromResourceManager(ctx, flow, direction)
1764 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00001765 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301766 direction = Upstream
1767 } else {
1768 direction = Downstream
1769 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301770
Girish Gowdracefae192020-03-19 18:14:10 -07001771 _, intfID, onuID, uniID, _, _, err := FlowExtractInfo(flow, direction)
1772 if err != nil {
1773 return err
1774 }
1775
1776 userKey := tpLockKey{intfID, onuID, uniID}
1777
1778 // Serialize flow removes on a per subscriber basis
1779 if f.perUserFlowHandleLock.TryLock(userKey) {
1780 f.clearFlowFromResourceManager(ctx, flow, direction) //TODO: Take care of the limitations
1781 f.perUserFlowHandleLock.Unlock(userKey)
1782 } else {
1783 // Ideally this should never happen
Girish Kumar2ad402b2020-03-20 19:45:12 +00001784 logger.Errorw("failed to acquire lock to remove flow, flow remove aborted", log.Fields{"flow": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001785 return errors.New("failed-to-acquire-per-user-lock")
1786 }
1787
1788 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001789}
1790
Girish Gowdra3d633032019-12-10 16:37:05 +05301791func (f *OpenOltFlowMgr) waitForFlowDeletesToCompleteForOnu(ctx context.Context, intfID uint32, onuID uint32,
1792 uniID uint32, ch chan bool) {
1793 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
1794 for {
1795 select {
1796 case <-time.After(20 * time.Millisecond):
1797 if flowDelRefCnt, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok || flowDelRefCnt == 0 {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001798 logger.Debug("pending flow deletes completed")
Girish Gowdra3d633032019-12-10 16:37:05 +05301799 ch <- true
1800 return
1801 }
1802 case <-ctx.Done():
Girish Kumar2ad402b2020-03-20 19:45:12 +00001803 logger.Error("flow delete wait handler routine canceled")
Girish Gowdra3d633032019-12-10 16:37:05 +05301804 return
1805 }
1806 }
1807}
1808
Esin Karamanae41e2b2019-12-17 18:13:13 +00001809//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
1810func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
1811 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
1812 if ethType, ok := classifierInfo[EthType]; ok {
1813 if ethType.(uint32) == IPv4EthType {
1814 if ipProto, ok := classifierInfo[IPProto]; ok {
1815 if ipProto.(uint32) == IgmpProto {
1816 return true
1817 }
1818 }
1819 }
1820 }
1821 }
1822 return false
1823}
1824
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001825// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05301826// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01001827func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001828 classifierInfo := make(map[string]interface{})
1829 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001830 var UsMeterID uint32
1831 var DsMeterID uint32
1832
Girish Kumar2ad402b2020-03-20 19:45:12 +00001833 logger.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001834 formulateClassifierInfoFromFlow(classifierInfo, flow)
1835
1836 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
1837 if err != nil {
1838 // Error logging is already done in the called function
1839 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001840 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301841 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001842
Esin Karamanccb714b2019-11-29 15:02:06 +00001843 if flows.HasGroup(flow) {
1844 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01001845 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00001846 }
1847
manikkaraj k17652a72019-05-06 09:06:36 -04001848 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00001849 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
1850 if err != nil {
1851 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01001852 return err
manikkaraj k17652a72019-05-06 09:06:36 -04001853 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001854
Girish Kumar2ad402b2020-03-20 19:45:12 +00001855 logger.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001856 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00001857
Humera Kouser94d7a842019-08-25 19:04:32 -04001858 if ethType, ok := classifierInfo[EthType]; ok {
1859 if ethType.(uint32) == LldpEthType {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001860 logger.Info("Adding LLDP flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01001861 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04001862 }
1863 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001864 if ipProto, ok := classifierInfo[IPProto]; ok {
1865 if ipProto.(uint32) == IPProtoDhcp {
1866 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05301867 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001868 logger.Debug("trap-dhcp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01001869 return f.addDHCPTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001870 }
1871 }
1872 }
1873 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001874 if isIgmpTrapDownstreamFlow(classifierInfo) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001875 logger.Debug("trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01001876 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001877 }
A R Karthick1f85b802019-10-11 05:06:05 +00001878
1879 f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
npujarec5762e2020-01-01 14:08:48 +05301880 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00001881
Chaitrashree G S90a17952019-11-14 21:51:21 -05001882 TpID, err := getTpIDFromFlow(flow)
1883 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001884 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 -05001885 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001886 logger.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001887 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07001888 UsMeterID = flows.GetMeterIdFromFlow(flow)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001889 logger.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001890 } else {
Scott Baker355d1742019-10-24 10:57:52 -07001891 DsMeterID = flows.GetMeterIdFromFlow(flow)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001892 logger.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001893
1894 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301895
1896 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
1897 if _, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001898 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 +05301899 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05301900 } else {
Girish Gowdra3d633032019-12-10 16:37:05 +05301901 pendingFlowDelComplete := make(chan bool)
1902 go f.waitForFlowDeletesToCompleteForOnu(ctx, intfID, onuID, uniID, pendingFlowDelComplete)
1903 select {
1904 case <-pendingFlowDelComplete:
Girish Kumar2ad402b2020-03-20 19:45:12 +00001905 logger.Debugw("all pending flow deletes completed", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
npujarec5762e2020-01-01 14:08:48 +05301906 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05301907
1908 case <-time.After(10 * time.Second):
Girish Kumarf26e4882020-03-05 06:49:10 +00001909 return olterrors.NewErrTimeout("pending-flow-deletes", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID}, nil)
Girish Gowdra3d633032019-12-10 16:37:05 +05301910 }
1911 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001912 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001913}
1914
Esin Karamanccb714b2019-11-29 15:02:06 +00001915// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08001916func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00001917 classifierInfo[PacketTagType] = DoubleTag
Girish Kumar2ad402b2020-03-20 19:45:12 +00001918 logger.Debugw("add-multicast-flow", log.Fields{"classifierInfo": classifierInfo, "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00001919
Esin Karaman65409d82020-03-18 10:58:18 +00001920 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00001921 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001922 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00001923 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00001924 //this variable acts like a switch. When it is set, multicast flows are classified by eth_dst.
1925 //otherwise, classification is based on ipv4_dst by default.
1926 //the variable can be configurable in the future; it can be read from a configuration path in the kv store.
1927 mcastFlowClassificationByEthDst := false
1928
1929 if mcastFlowClassificationByEthDst {
1930 //replace ipDst with ethDst
1931 if ipv4Dst, ok := classifierInfo[Ipv4Dst]; ok &&
1932 flows.IsMulticastIp(ipv4Dst.(uint32)) {
1933 // replace ipv4_dst classifier with eth_dst
1934 multicastMac := flows.ConvertToMulticastMacBytes(ipv4Dst.(uint32))
1935 delete(classifierInfo, Ipv4Dst)
1936 classifierInfo[EthDst] = multicastMac
Girish Kumar2ad402b2020-03-20 19:45:12 +00001937 logger.Debugw("multicast-ip-to-mac-conversion-success", log.Fields{"ip:": ipv4Dst.(uint32), "mac:": multicastMac})
Esin Karamanfcddfcf2020-03-04 13:34:38 +00001938 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001939 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00001940 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00001941
David K. Bainbridge794735f2020-02-11 21:01:37 -08001942 onuID := NoneOnuID
1943 uniID := NoneUniID
1944 gemPortID := NoneGemPortID
Esin Karamanccb714b2019-11-29 15:02:06 +00001945
David K. Bainbridge794735f2020-02-11 21:01:37 -08001946 flowStoreCookie := getFlowStoreCookie(classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05301947 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001948 logger.Debugw("multicast-flow-exists-not-re-adding", log.Fields{"classifierInfo": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001949 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00001950 }
npujarec5762e2020-01-01 14:08:48 +05301951 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanccb714b2019-11-29 15:02:06 +00001952 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301953 return olterrors.NewErrNotFound("multicast-flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001954 "interface-id": networkInterfaceID,
1955 "onu-id": onuID,
1956 "uni-id": uniID,
1957 "gem-port-id": gemPortID,
1958 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00001959 err)
Esin Karamanccb714b2019-11-29 15:02:06 +00001960 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001961 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1962 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001963 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00001964 }
1965 groupID := actionInfo[GroupID].(uint32)
1966 multicastFlow := openoltpb2.Flow{
1967 FlowId: flowID,
1968 FlowType: Multicast,
1969 NetworkIntfId: int32(networkInterfaceID),
1970 GroupId: groupID,
1971 Classifier: classifierProto,
1972 Priority: int32(flow.Priority),
1973 Cookie: flow.Cookie}
1974
David K. Bainbridge794735f2020-02-11 21:01:37 -08001975 if err = f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001976 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001977 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001978 logger.Debug("multicast flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001979 //get cached group
1980 group, _, err := f.GetFlowGroupFromKVStore(ctx, groupID, true)
1981 if err == nil {
1982 //calling groupAdd to set group members after multicast flow creation
Andrea Campanellac63bba92020-03-10 17:01:04 +01001983 if err = f.ModifyGroup(ctx, group); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001984 //cached group can be removed now
1985 f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001986 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001987 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00001988 }
1989 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001990
1991 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &multicastFlow, flowStoreCookie, MulticastFlow, flowID, flow.Id)
1992 if err = f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
1993 int32(onuID),
1994 int32(uniID),
1995 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001996 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001997 }
1998 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00001999}
2000
Esin Karaman65409d82020-03-18 10:58:18 +00002001//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2002func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2003 if inPort, ok := classifierInfo[InPort]; ok {
2004 nniInterfaceID, err := IntfIDFromNniPortNum(inPort.(uint32))
2005 if err != nil {
2006 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2007 }
2008 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002009 }
Esin Karaman65409d82020-03-18 10:58:18 +00002010 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302011 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002012 if e == nil && len(nniPorts) > 0 {
2013 return nniPorts[0], nil
2014 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302015 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002016}
2017
2018// AddGroup add or update the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002019func (f *OpenOltFlowMgr) AddGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002020 logger.Infow("add-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002021 if group == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002022 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002023 }
2024
2025 groupToOlt := openoltpb2.Group{
2026 GroupId: group.Desc.GroupId,
2027 Command: openoltpb2.Group_SET_MEMBERS,
2028 Action: f.buildGroupAction(),
2029 }
2030
Girish Kumar2ad402b2020-03-20 19:45:12 +00002031 logger.Debugw("Sending group to device", log.Fields{"groupToOlt": groupToOlt})
npujarec5762e2020-01-01 14:08:48 +05302032 _, err := f.deviceHandler.Client.PerformGroupOperation(ctx, &groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002033 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002034 return olterrors.NewErrAdapter("add-group-operation-failed", log.Fields{"groupToOlt": groupToOlt}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002035 }
2036 // group members not created yet. So let's store the group
npujarec5762e2020-01-01 14:08:48 +05302037 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, true); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002038 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002039 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002040 logger.Debugw("add-group operation performed on the device successfully ", log.Fields{"groupToOlt": groupToOlt})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002041 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002042}
2043
2044//buildGroupAction creates and returns a group action
2045func (f *OpenOltFlowMgr) buildGroupAction() *openoltpb2.Action {
2046 var actionCmd openoltpb2.ActionCmd
2047 var action openoltpb2.Action
2048 action.Cmd = &actionCmd
2049 //pop outer vlan
2050 action.Cmd.RemoveOuterTag = true
2051 return &action
2052}
2053
2054// ModifyGroup updates the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002055func (f *OpenOltFlowMgr) ModifyGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002056 logger.Infow("modify-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002057 if group == nil || group.Desc == nil {
Jonathan Hartc4b19112020-04-02 11:21:45 -07002058 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002059 }
2060
Andrea Campanellac63bba92020-03-10 17:01:04 +01002061 newGroup := f.buildGroup(group.Desc.GroupId, group.Desc.Buckets)
Esin Karamanccb714b2019-11-29 15:02:06 +00002062 //get existing members of the group
npujarec5762e2020-01-01 14:08:48 +05302063 val, groupExists, err := f.GetFlowGroupFromKVStore(ctx, group.Desc.GroupId, false)
Esin Karamanccb714b2019-11-29 15:02:06 +00002064
2065 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002066 return olterrors.NewErrNotFound("flow-group-in-kv-store", log.Fields{"groupId": group.Desc.GroupId}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002067 }
2068
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002069 var current *openoltpb2.Group // represents the group on the device
Esin Karamanccb714b2019-11-29 15:02:06 +00002070 if groupExists {
2071 // group already exists
2072 current = f.buildGroup(group.Desc.GroupId, val.Desc.GetBuckets())
Girish Kumar2ad402b2020-03-20 19:45:12 +00002073 logger.Debugw("modify-group: group exists.", log.Fields{"group on the device": val, "new": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002074 } else {
2075 current = f.buildGroup(group.Desc.GroupId, nil)
2076 }
2077
Girish Kumar2ad402b2020-03-20 19:45:12 +00002078 logger.Debugw("modify-group: comparing current and new.", log.Fields{"group on the device": current, "new": newGroup})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002079 // get members to be added
Andrea Campanellac63bba92020-03-10 17:01:04 +01002080 membersToBeAdded := f.findDiff(current, newGroup)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002081 // get members to be removed
Andrea Campanellac63bba92020-03-10 17:01:04 +01002082 membersToBeRemoved := f.findDiff(newGroup, current)
Esin Karamanccb714b2019-11-29 15:02:06 +00002083
Girish Kumar2ad402b2020-03-20 19:45:12 +00002084 logger.Infow("modify-group -> differences found", log.Fields{"membersToBeAdded": membersToBeAdded,
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002085 "membersToBeRemoved": membersToBeRemoved, "groupId": group.Desc.GroupId})
Esin Karamanccb714b2019-11-29 15:02:06 +00002086
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002087 groupToOlt := openoltpb2.Group{
2088 GroupId: group.Desc.GroupId,
2089 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002090 var errAdd, errRemoved error
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002091 if membersToBeAdded != nil && len(membersToBeAdded) > 0 {
2092 groupToOlt.Command = openoltpb2.Group_ADD_MEMBERS
2093 groupToOlt.Members = membersToBeAdded
2094 //execute addMembers
Andrea Campanellac63bba92020-03-10 17:01:04 +01002095 errAdd = f.callGroupAddRemove(&groupToOlt)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002096 }
2097 if membersToBeRemoved != nil && len(membersToBeRemoved) > 0 {
2098 groupToOlt.Command = openoltpb2.Group_REMOVE_MEMBERS
2099 groupToOlt.Members = membersToBeRemoved
2100 //execute removeMembers
Andrea Campanellac63bba92020-03-10 17:01:04 +01002101 errRemoved = f.callGroupAddRemove(&groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002102 }
2103
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002104 //save the modified group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002105 if errAdd == nil && errRemoved == nil {
npujarec5762e2020-01-01 14:08:48 +05302106 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, false); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002107 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002108 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002109 logger.Debugw("modify-group was success. Storing the group", log.Fields{"group": group, "existingGroup": current})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002110 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002111 logger.Warnw("One of the group add/remove operations has failed. Cannot save group modifications",
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002112 log.Fields{"group": group})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002113 if errAdd != nil {
2114 return errAdd
2115 }
2116 return errRemoved
Esin Karamanccb714b2019-11-29 15:02:06 +00002117 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002118 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002119}
2120
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002121//callGroupAddRemove performs add/remove buckets operation for the indicated group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002122func (f *OpenOltFlowMgr) callGroupAddRemove(group *openoltpb2.Group) error {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002123 if err := f.performGroupOperation(group); err != nil {
2124 st, _ := status.FromError(err)
2125 //ignore already exists error code
2126 if st.Code() != codes.AlreadyExists {
Andrea Campanellac63bba92020-03-10 17:01:04 +01002127 return olterrors.NewErrGroupOp("groupAddRemove", group.GroupId, log.Fields{"status": st}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002128 }
2129 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002130 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002131}
2132
2133//findDiff compares group members and finds members which only exists in groups2
2134func (f *OpenOltFlowMgr) findDiff(group1 *openoltpb2.Group, group2 *openoltpb2.Group) []*openoltpb2.GroupMember {
2135 var members []*openoltpb2.GroupMember
2136 for _, bucket := range group2.Members {
2137 if !f.contains(group1.Members, bucket) {
2138 // bucket does not exist and must be added
2139 members = append(members, bucket)
2140 }
2141 }
2142 return members
2143}
2144
2145//contains returns true if the members list contains the given member; false otherwise
2146func (f *OpenOltFlowMgr) contains(members []*openoltpb2.GroupMember, member *openoltpb2.GroupMember) bool {
2147 for _, groupMember := range members {
2148 if groupMember.InterfaceId == member.InterfaceId {
2149 return true
2150 }
2151 }
2152 return false
2153}
2154
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002155//performGroupOperation call performGroupOperation operation of openolt proto
2156func (f *OpenOltFlowMgr) performGroupOperation(group *openoltpb2.Group) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002157 logger.Debugw("Sending group to device", log.Fields{"groupToOlt": group, "command": group.Command})
Esin Karamanccb714b2019-11-29 15:02:06 +00002158 _, err := f.deviceHandler.Client.PerformGroupOperation(context.Background(), group)
2159 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002160 return olterrors.NewErrAdapter("group-operation-failed", log.Fields{"groupToOlt": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002161 }
Girish Kumarf26e4882020-03-05 06:49:10 +00002162 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002163}
2164
2165//buildGroup build openoltpb2.Group from given group id and bucket list
2166func (f *OpenOltFlowMgr) buildGroup(groupID uint32, buckets []*ofp.OfpBucket) *openoltpb2.Group {
2167 group := openoltpb2.Group{
2168 GroupId: groupID}
2169 // create members of the group
2170 if buckets != nil {
2171 for _, ofBucket := range buckets {
2172 member := f.buildMember(ofBucket)
2173 if member != nil && !f.contains(group.Members, member) {
2174 group.Members = append(group.Members, member)
2175 }
2176 }
2177 }
2178 return &group
2179}
2180
2181//buildMember builds openoltpb2.GroupMember from an OpenFlow bucket
2182func (f *OpenOltFlowMgr) buildMember(ofBucket *ofp.OfpBucket) *openoltpb2.GroupMember {
2183 var outPort uint32
2184 outPortFound := false
2185 for _, ofAction := range ofBucket.Actions {
2186 if ofAction.Type == ofp.OfpActionType_OFPAT_OUTPUT {
2187 outPort = ofAction.GetOutput().Port
2188 outPortFound = true
2189 }
2190 }
2191
2192 if !outPortFound {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002193 logger.Debugw("bucket skipped since no out port found in it",
Esin Karamanccb714b2019-11-29 15:02:06 +00002194 log.Fields{"ofBucket": ofBucket})
2195 return nil
2196 }
2197 interfaceID := IntfIDFromUniPortNum(outPort)
Girish Kumar2ad402b2020-03-20 19:45:12 +00002198 logger.Debugw("got associated interface id of the port", log.Fields{"portNumber:": outPort, "interfaceId:": interfaceID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002199 if groupInfo, ok := f.interfaceToMcastQueueMap[interfaceID]; ok {
2200 member := openoltpb2.GroupMember{
2201 InterfaceId: interfaceID,
2202 InterfaceType: openoltpb2.GroupMember_PON,
2203 GemPortId: groupInfo.gemPortID,
2204 Priority: groupInfo.servicePriority,
2205 }
2206 //add member to the group
2207 return &member
2208 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002209 logger.Warnf("bucket skipped since interface-2-gem mapping cannot be found",
Esin Karamanccb714b2019-11-29 15:02:06 +00002210 log.Fields{"ofBucket": ofBucket})
2211 return nil
2212}
2213
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002214//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04002215func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002216
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002217 onuDev, err := f.getOnuDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302218 if err != nil {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002219 logger.Errorw("couldnt-find-onu-child-device", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
2220 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302221 }
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002222 logger.Debugw("Got child device from OLT device handler", log.Fields{"deviceId": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002223
Manikkaraj kb1d51442019-07-23 10:41:02 -04002224 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002225 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Girish Kumar2ad402b2020-03-20 19:45:12 +00002226 logger.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
manikkaraj k17652a72019-05-06 09:06:36 -04002227 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
2228 tpDownloadMsg,
2229 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
2230 f.deviceHandler.deviceType,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002231 onuDev.deviceType,
2232 onuDev.deviceID,
2233 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002234 if sendErr != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002235 return olterrors.NewErrCommunication("send-techprofile-download-request", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002236 "toAdapter": onuDev.deviceType, "onuId": onuDev.deviceID,
2237 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002238 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002239 logger.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302240 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302241}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002242
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302243//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002244func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302245
2246 f.lockCache.Lock()
2247 defer f.lockCache.Unlock()
2248 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2249 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002250 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002251 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302252 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002253 logger.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002254 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002255}
2256
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302257//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302258func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302259 f.lockCache.Lock()
2260 defer f.lockCache.Unlock()
2261 onugem := f.onuGemInfo[intfID]
2262 // update the gem to the local cache as well as to kv strore
2263 for idx, onu := range onugem {
2264 if onu.OnuID == onuID {
2265 // check if gem already exists , else update the cache and kvstore
2266 for _, gem := range onu.GemPorts {
2267 if gem == gemPort {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002268 logger.Debugw("Gem already in cache, no need to update cache and kv store",
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302269 log.Fields{"gem": gemPort})
2270 return
2271 }
2272 }
2273 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
2274 f.onuGemInfo[intfID] = onugem
2275 }
2276 }
npujarec5762e2020-01-01 14:08:48 +05302277 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302278 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002279 logger.Errorw("Failed to add gem to onu", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002280 return
2281 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002282}
2283
2284// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002285
2286//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
2287func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302288
2289 f.lockCache.Lock()
2290 defer f.lockCache.Unlock()
2291
Girish Kumar2ad402b2020-03-20 19:45:12 +00002292 logger.Debugw("Getting ONU ID from GEM port and PON port", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPortId": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302293 // get onuid from the onugem info cache
2294 onugem := f.onuGemInfo[intfID]
2295 for _, onu := range onugem {
2296 for _, gem := range onu.GemPorts {
2297 if gem == gemPortID {
2298 return onu.OnuID, nil
2299 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002300 }
2301 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302302 return uint32(0), olterrors.NewErrNotFound("onu-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002303 "serial-number": serialNumber,
2304 "interface-id": intfID,
2305 "gem-port-id": gemPortID},
Girish Kumarf26e4882020-03-05 06:49:10 +00002306 nil)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002307}
2308
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002309//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302310func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002311 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002312 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002313 var err error
2314
2315 if packetIn.IntfType == "pon" {
2316 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002317 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002318 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002319 return logicalPortNum, err
2320 }
2321 if packetIn.PortNo != 0 {
2322 logicalPortNum = packetIn.PortNo
2323 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002324 uniID := uint32(0) // FIXME - multi-uni support
2325 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002326 }
2327 // Store the gem port through which the packet_in came. Use the same gem port for packet_out
npujarec5762e2020-01-01 14:08:48 +05302328 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002329 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002330 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002331 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002332 logger.Debugw("Retrieved logicalport from packet-in", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08002333 "logicalPortNum": logicalPortNum,
2334 "IntfType": packetIn.IntfType,
2335 "packet": hex.EncodeToString(packetIn.Pkt),
2336 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002337 return logicalPortNum, nil
2338}
2339
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002340//GetPacketOutGemPortID returns gemPortId
npujarec5762e2020-01-01 14:08:48 +05302341func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002342 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002343 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302344
2345 f.lockCache.Lock()
2346 defer f.lockCache.Unlock()
2347 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum}
2348
2349 gemPortID, ok := f.packetInGemPort[pktInkey]
2350 if ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002351 logger.Debugw("Found gemport for pktin key", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302352 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002353 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302354 //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 +05302355 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, intfID, onuID, portNum)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302356 if err == nil {
2357 if gemPortID != 0 {
2358 f.packetInGemPort[pktInkey] = gemPortID
Girish Kumar2ad402b2020-03-20 19:45:12 +00002359 logger.Debugw("Found gem port from kv store and updating cache with gemport",
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302360 log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
2361 return gemPortID, nil
2362 }
2363 }
Girish Kumarf26e4882020-03-05 06:49:10 +00002364 return uint32(0), olterrors.NewErrNotFound("gem-port", log.Fields{"pktinkey": pktInkey, "gem": gemPortID}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002365}
2366
npujarec5762e2020-01-01 14:08:48 +05302367func installFlowOnAllGemports(ctx context.Context,
2368 f1 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32,
Manikkaraj kb1d51442019-07-23 10:41:02 -04002369 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
David K. Bainbridge794735f2020-02-11 21:01:37 -08002370 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32) error,
npujarec5762e2020-01-01 14:08:48 +05302371 f2 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05302372 classifier map[string]interface{}, action map[string]interface{},
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302373 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05302374 ) error,
Manikkaraj kb1d51442019-07-23 10:41:02 -04002375 args map[string]uint32,
2376 classifier map[string]interface{}, action map[string]interface{},
2377 logicalFlow *ofp.OfpFlowStats,
2378 gemPorts []uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05302379 TpInst *tp.TechProfile,
Manikkaraj kb1d51442019-07-23 10:41:02 -04002380 FlowType string,
salmansiddiqui7ac62132019-08-22 03:58:50 +00002381 vlanID ...uint32) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002382 logger.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
Girish Gowdrafae935c2020-02-17 19:21:44 +05302383
2384 for _, gemPortAttribute := range TpInst.UpstreamGemPortAttributeList {
2385 var gemPortID uint32
2386 // The bit mapping for a gemport is expressed in tech-profile as a binary string. For example, 0b00000001
2387 // We need to trim prefix "0b", before further processing
2388 // Once the "0b" prefix is trimmed, we iterate each character in the string to identify which index
2389 // in the string is set to binary bit 1 (expressed as char '1' in the binary string).
2390 for pos, pbitSet := range strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix) {
2391 // If a particular character in the string is set to '1', identify the index of this character from
2392 // the LSB position which marks the PCP bit consumed by the given gem port.
2393 // This PCP bit now becomes a classifier in the flow.
2394 if pbitSet == BinaryBit1 {
2395 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
2396 gemPortID = gemPortAttribute.GemportID
2397 if FlowType == HsiaFlow || FlowType == DhcpFlow || FlowType == IgmpFlow {
2398 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
2399 } else if FlowType == EapolFlow {
2400 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0])
2401 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002402 logger.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
Girish Gowdrafae935c2020-02-17 19:21:44 +05302403 return
2404 }
2405 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002406 }
2407 }
2408}
2409
David K. Bainbridge794735f2020-02-11 21:01:37 -08002410func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002411 logger.Debug("Adding trap-dhcp-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002412 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002413 classifier[PacketTagType] = DoubleTag
2414 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002415 /* We manage flowId resource pool on per PON port basis.
2416 Since this situation is tricky, as a hack, we pass the NNI port
2417 index (network_intf_id) as PON port Index for the flowId resource
2418 pool. Also, there is no ONU Id available for trapping DHCP packets
2419 on NNI port, use onu_id as -1 (invalid)
2420 ****************** CAVEAT *******************
2421 This logic works if the NNI Port Id falls within the same valid
2422 range of PON Port Ids. If this doesn't work for some OLT Vendor
2423 we need to have a re-look at this.
2424 *********************************************
2425 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002426 onuID := -1
2427 uniID := -1
2428 gemPortID := -1
2429 allocID := -1
David K. Bainbridge794735f2020-02-11 21:01:37 -08002430 networkInterfaceID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302431 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302432 return olterrors.NewErrNotFound("nni-intreface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002433 "classifier": classifier,
2434 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002435 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302436 }
2437
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002438 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05302439 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002440 logger.Debug("Flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002441 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002442 }
npujarec5762e2020-01-01 14:08:48 +05302443 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002444 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302445 return olterrors.NewErrNotFound("dhcp-trap-nni-flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002446 "interface-id": networkInterfaceID,
2447 "onu-id": onuID,
2448 "uni-id": uniID,
2449 "gem-port-id": gemPortID,
2450 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00002451 err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002452 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002453 classifierProto, err := makeOpenOltClassifierField(classifier)
2454 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002455 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002456 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002457 logger.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002458 actionProto, err := makeOpenOltActionField(action)
2459 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002460 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002461 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002462 logger.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002463 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2464 OnuId: int32(onuID), // OnuId not required
2465 UniId: int32(uniID), // UniId not used
2466 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002467 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002468 AllocId: int32(allocID), // AllocId not used
2469 NetworkIntfId: int32(networkInterfaceID),
2470 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002471 Classifier: classifierProto,
2472 Action: actionProto,
2473 Priority: int32(logicalFlow.Priority),
2474 Cookie: logicalFlow.Cookie,
2475 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002476 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002477 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002478 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002479 logger.Debug("DHCP trap on NNI flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002480 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
2481 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
2482 int32(onuID),
2483 int32(uniID),
2484 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002485 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002486 }
2487 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002488}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002489
Esin Karamanae41e2b2019-12-17 18:13:13 +00002490//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2491func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2492 var packetType string
2493 ovid, ivid := false, false
2494 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2495 vid := vlanID & VlanvIDMask
2496 if vid != ReservedVlan {
2497 ovid = true
2498 }
2499 }
2500 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2501 vid := uint32(metadata)
2502 if vid != ReservedVlan {
2503 ivid = true
2504 }
2505 }
2506 if ovid && ivid {
2507 packetType = DoubleTag
2508 } else if !ovid && !ivid {
2509 packetType = Untagged
2510 } else {
2511 packetType = SingleTag
2512 }
2513 return packetType
2514}
2515
2516//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002517func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002518 logger.Debugw("Adding igmp-trap-of-nni-flow", log.Fields{"classifierInfo": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002519 action := make(map[string]interface{})
2520 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2521 action[TrapToHost] = true
2522 /* We manage flowId resource pool on per PON port basis.
2523 Since this situation is tricky, as a hack, we pass the NNI port
2524 index (network_intf_id) as PON port Index for the flowId resource
2525 pool. Also, there is no ONU Id available for trapping packets
2526 on NNI port, use onu_id as -1 (invalid)
2527 ****************** CAVEAT *******************
2528 This logic works if the NNI Port Id falls within the same valid
2529 range of PON Port Ids. If this doesn't work for some OLT Vendor
2530 we need to have a re-look at this.
2531 *********************************************
2532 */
2533 onuID := -1
2534 uniID := -1
2535 gemPortID := -1
2536 allocID := -1
2537 networkInterfaceID, err := getNniIntfID(classifier, action)
2538 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302539 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002540 "classifier": classifier,
2541 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002542 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002543 }
2544 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05302545 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002546 logger.Debug("igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002547 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002548 }
npujarec5762e2020-01-01 14:08:48 +05302549 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002550 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302551 return olterrors.NewErrNotFound("igmp-flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002552 "interface-id": networkInterfaceID,
2553 "onu-id": onuID,
2554 "uni-id": uniID,
2555 "gem-port-id": gemPortID,
2556 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00002557 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002558 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002559 classifierProto, err := makeOpenOltClassifierField(classifier)
2560 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002561 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002562 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002563 logger.Debugw("Created classifier proto for the IGMP flow", log.Fields{"classifier": *classifierProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002564 actionProto, err := makeOpenOltActionField(action)
2565 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002566 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002567 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002568 logger.Debugw("Created action proto for the IGMP flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002569 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2570 OnuId: int32(onuID), // OnuId not required
2571 UniId: int32(uniID), // UniId not used
2572 FlowId: flowID,
2573 FlowType: Downstream,
2574 AllocId: int32(allocID), // AllocId not used
2575 NetworkIntfId: int32(networkInterfaceID),
2576 GemportId: int32(gemPortID), // GemportId not used
2577 Classifier: classifierProto,
2578 Action: actionProto,
2579 Priority: int32(logicalFlow.Priority),
2580 Cookie: logicalFlow.Cookie,
2581 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002582 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002583 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002584 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002585 logger.Debug("IGMP Trap on NNI flow added to device successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002586 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
2587 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
2588 int32(onuID),
2589 int32(uniID),
2590 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002591 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002592 }
2593 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002594}
2595
salmansiddiqui7ac62132019-08-22 03:58:50 +00002596func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2597 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302598 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002599 }
2600 if Dir == tp_pb.Direction_UPSTREAM {
2601 return "upstream", nil
2602 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2603 return "downstream", nil
2604 }
2605 return "", nil
2606}
2607
npujarec5762e2020-01-01 14:08:48 +05302608func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Gamze Abakafee36392019-10-03 11:17:24 +00002609 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst *tp.TechProfile, gemPorts []uint32,
2610 TpID uint32, uni string) {
2611 var gemPort uint32
2612 intfID := args[IntfID]
2613 onuID := args[OnuID]
2614 uniID := args[UniID]
2615 portNo := args[PortNo]
2616 allocID := TpInst.UsScheduler.AllocID
salmansiddiqui7ac62132019-08-22 03:58:50 +00002617 if ipProto, ok := classifierInfo[IPProto]; ok {
2618 if ipProto.(uint32) == IPProtoDhcp {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002619 logger.Info("Adding DHCP flow")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002620 if pcp, ok := classifierInfo[VlanPcp]; ok {
2621 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2622 tp_pb.Direction_UPSTREAM,
2623 pcp.(uint32))
2624 //Adding DHCP upstream flow
npujarec5762e2020-01-01 14:08:48 +05302625 f.addDHCPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002626 } else {
2627 //Adding DHCP upstream flow to all gemports
Girish Gowdrafae935c2020-02-17 19:21:44 +05302628 installFlowOnAllGemports(ctx, f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, DhcpFlow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002629 }
2630
2631 } else if ipProto == IgmpProto {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002632 logger.Infow("Adding Us IGMP flow", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "classifierInfo:": classifierInfo})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002633 if pcp, ok := classifierInfo[VlanPcp]; ok {
2634 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2635 tp_pb.Direction_UPSTREAM,
2636 pcp.(uint32))
npujarec5762e2020-01-01 14:08:48 +05302637 f.addIGMPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002638 } else {
2639 //Adding IGMP upstream flow to all gem ports
Girish Gowdrafae935c2020-02-17 19:21:44 +05302640 installFlowOnAllGemports(ctx, f.addIGMPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, IgmpFlow)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002641 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002642 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002643 logger.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002644 return
2645 }
2646 } else if ethType, ok := classifierInfo[EthType]; ok {
2647 if ethType.(uint32) == EapEthType {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002648 logger.Info("Adding EAPOL flow")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002649 var vlanID uint32
2650 if val, ok := classifierInfo[VlanVid]; ok {
2651 vlanID = (val.(uint32)) & VlanvIDMask
2652 } else {
2653 vlanID = DefaultMgmtVlan
2654 }
2655 if pcp, ok := classifierInfo[VlanPcp]; ok {
2656 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2657 tp_pb.Direction_UPSTREAM,
2658 pcp.(uint32))
2659
Girish Gowdrafae935c2020-02-17 19:21:44 +05302660 f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002661 } else {
Girish Gowdrafae935c2020-02-17 19:21:44 +05302662 installFlowOnAllGemports(ctx, nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, EapolFlow, vlanID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002663 }
2664 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002665 } else if _, ok := actionInfo[PushVlan]; ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002666 logger.Info("Adding upstream data rule")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002667 if pcp, ok := classifierInfo[VlanPcp]; ok {
2668 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2669 tp_pb.Direction_UPSTREAM,
2670 pcp.(uint32))
2671 //Adding HSIA upstream flow
npujarec5762e2020-01-01 14:08:48 +05302672 f.addUpstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002673 } else {
2674 //Adding HSIA upstream flow to all gemports
Girish Gowdrafae935c2020-02-17 19:21:44 +05302675 installFlowOnAllGemports(ctx, f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002676 }
2677 } else if _, ok := actionInfo[PopVlan]; ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002678 logger.Info("Adding Downstream data rule")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002679 if pcp, ok := classifierInfo[VlanPcp]; ok {
2680 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05002681 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00002682 pcp.(uint32))
2683 //Adding HSIA downstream flow
npujarec5762e2020-01-01 14:08:48 +05302684 f.addDownstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002685 } else {
2686 //Adding HSIA downstream flow to all gemports
Girish Gowdrafae935c2020-02-17 19:21:44 +05302687 installFlowOnAllGemports(ctx, f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002688 }
2689 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002690 logger.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002691 return
2692 }
2693 // Send Techprofile download event to child device in go routine as it takes time
2694 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, TpID)
2695}
2696
Gamze Abakafee36392019-10-03 11:17:24 +00002697func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
2698 flowIDList := f.flowsUsedByGemPort[gemPK]
2699 if len(flowIDList) > 1 {
2700 return true
2701 }
2702 return false
2703}
2704
npujarec5762e2020-01-01 14:08:48 +05302705func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
2706 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002707 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2708 for _, currentGemPort := range currentGemPorts {
2709 for _, tpGemPort := range tpGemPorts {
2710 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
2711 return true, currentGemPort
2712 }
2713 }
2714 }
Girish Gowdra54934262019-11-13 14:19:55 +05302715 if tpInst.InstanceCtrl.Onu == "single-instance" {
2716 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
npujarec5762e2020-01-01 14:08:48 +05302717 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, uint32(onuID), uint32(uniID), tpID)
2718 f.DeleteTechProfileInstance(ctx, ponIntf, uint32(onuID), uint32(uniID), "", tpID)
Girish Gowdra54934262019-11-13 14:19:55 +05302719
2720 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
2721 // still be used on other uni ports.
2722 // So, we need to check and make sure that no other gem port is referring to the given TP ID
2723 // on any other uni port.
npujarec5762e2020-01-01 14:08:48 +05302724 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID)
Girish Kumar2ad402b2020-03-20 19:45:12 +00002725 logger.Debugw("got single instance tp instances", log.Fields{"tpInstances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05302726 for i := 0; i < len(tpInstances); i++ {
2727 tpI := tpInstances[i]
2728 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05302729 for _, tpGemPort := range tpGemPorts {
2730 if tpGemPort.GemportID != gemPortID {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002731 logger.Debugw("single instance tp is in use by gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302732 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05302733 }
2734 }
2735 }
2736 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002737 logger.Debug("tech profile is not in use by any gem")
Gamze Abakafee36392019-10-03 11:17:24 +00002738 return false, 0
2739}
2740
salmansiddiqui7ac62132019-08-22 03:58:50 +00002741func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002742 for _, field := range flows.GetOfbFields(flow) {
2743 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002744 classifierInfo[EthType] = field.GetEthType()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002745 logger.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002746 } else if field.Type == flows.ETH_DST {
2747 classifierInfo[EthDst] = field.GetEthDst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002748 logger.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07002749 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002750 classifierInfo[IPProto] = field.GetIpProto()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002751 logger.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002752 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002753 classifierInfo[InPort] = field.GetPort()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002754 logger.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002755 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05302756 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Girish Kumar2ad402b2020-03-20 19:45:12 +00002757 logger.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002758 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002759 classifierInfo[VlanPcp] = field.GetVlanPcp()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002760 logger.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002761 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002762 classifierInfo[UDPDst] = field.GetUdpDst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002763 logger.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002764 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002765 classifierInfo[UDPSrc] = field.GetUdpSrc()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002766 logger.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002767 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002768 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002769 logger.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002770 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002771 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002772 logger.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002773 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002774 classifierInfo[Metadata] = field.GetTableMetadata()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002775 logger.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07002776 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002777 classifierInfo[TunnelID] = field.GetTunnelId()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002778 logger.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002779 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002780 logger.Errorw("Un supported field type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002781 return
2782 }
2783 }
2784}
2785
2786func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07002787 for _, action := range flows.GetActions(flow) {
2788 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002789 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002790 actionInfo[Output] = out.GetPort()
Girish Kumar2ad402b2020-03-20 19:45:12 +00002791 logger.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002792 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002793 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002794 }
Scott Baker355d1742019-10-24 10:57:52 -07002795 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002796 actionInfo[PopVlan] = true
Girish Kumar2ad402b2020-03-20 19:45:12 +00002797 logger.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002798 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002799 if out := action.GetPush(); out != nil {
2800 if tpid := out.GetEthertype(); tpid != 0x8100 {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002801 logger.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002802 } else {
2803 actionInfo[PushVlan] = true
2804 actionInfo[TPID] = tpid
Girish Kumar2ad402b2020-03-20 19:45:12 +00002805 logger.Debugw("action-type-push-vlan",
salmansiddiqui7ac62132019-08-22 03:58:50 +00002806 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
2807 }
2808 }
Scott Baker355d1742019-10-24 10:57:52 -07002809 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002810 if out := action.GetSetField(); out != nil {
2811 if field := out.GetField(); field != nil {
2812 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00002813 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002814 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002815 /*logger.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
Esin Karamanccb714b2019-11-29 15:02:06 +00002816 formulateSetFieldActionInfoFromFlow(field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002817 }
2818 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002819 } else if action.Type == flows.GROUP {
2820 formulateGroupActionInfoFromFlow(action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002821 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002822 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002823 }
2824 }
2825 return nil
2826}
2827
Esin Karamanccb714b2019-11-29 15:02:06 +00002828func formulateSetFieldActionInfoFromFlow(field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
2829 if ofbField := field.GetOfbField(); ofbField != nil {
2830 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
2831 if vlan := ofbField.GetVlanVid(); vlan != 0 {
2832 actionInfo[VlanVid] = vlan & 0xfff
Girish Kumar2ad402b2020-03-20 19:45:12 +00002833 logger.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002834 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002835 logger.Error("No Invalid vlan id in set vlan-vid action")
Esin Karamanccb714b2019-11-29 15:02:06 +00002836 }
2837 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002838 logger.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00002839 }
2840 }
2841}
2842
2843func formulateGroupActionInfoFromFlow(action *ofp.OfpAction, actionInfo map[string]interface{}) {
2844 if action.GetGroup() == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002845 logger.Warn("No group entry found in the group action")
Esin Karamanccb714b2019-11-29 15:02:06 +00002846 } else {
2847 actionInfo[GroupID] = action.GetGroup().GroupId
Girish Kumar2ad402b2020-03-20 19:45:12 +00002848 logger.Debugw("action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002849 }
2850}
2851
salmansiddiqui7ac62132019-08-22 03:58:50 +00002852func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002853 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002854 logger.Debug("Controller bound trap flows, getting inport from tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002855 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2856 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002857 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002858 classifierInfo[InPort] = uniPort
Girish Kumar2ad402b2020-03-20 19:45:12 +00002859 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 +00002860 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +05302861 return olterrors.NewErrNotFound("child-in-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002862 "reason": "upstream pon-to-controller-flow, NO-inport-in-tunnelid",
Girish Kumarf26e4882020-03-05 06:49:10 +00002863 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002864 }
2865 }
2866 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002867 logger.Debug("Non-Controller flows, getting uniport from tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002868 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07002869 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002870 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002871 actionInfo[Output] = uniPort
Girish Kumar2ad402b2020-03-20 19:45:12 +00002872 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 +00002873 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +05302874 return olterrors.NewErrNotFound("out-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002875 "reason": "downstream-nni-to-pon-port-flow, no-outport-in-tunnelid",
Girish Kumarf26e4882020-03-05 06:49:10 +00002876 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002877 }
2878 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2879 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002880 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002881 classifierInfo[InPort] = uniPort
Girish Kumar2ad402b2020-03-20 19:45:12 +00002882 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 -07002883 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002884 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +05302885 return olterrors.NewErrNotFound("nni-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002886 "reason": "upstream-pon-to-nni-port-flow, no-inport-in-tunnelid",
2887 "in-port": classifierInfo[InPort].(uint32),
2888 "out-port": actionInfo[Output].(uint32),
Girish Kumarf26e4882020-03-05 06:49:10 +00002889 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002890 }
2891 }
2892 }
2893 return nil
2894}
Gamze Abakafee36392019-10-03 11:17:24 +00002895
Chaitrashree G S90a17952019-11-14 21:51:21 -05002896func getTpIDFromFlow(flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00002897 /* Metadata 8 bytes:
2898 Most Significant 2 Bytes = Inner VLAN
2899 Next 2 Bytes = Tech Profile ID(TPID)
2900 Least Significant 4 Bytes = Port ID
2901 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
2902 subscriber related flows.
2903 */
2904 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
2905 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00002906 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00002907 }
2908 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002909 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00002910}
2911
2912func appendUnique(slice []uint32, item uint32) []uint32 {
2913 for _, sliceElement := range slice {
2914 if sliceElement == item {
2915 return slice
2916 }
2917 }
2918 return append(slice, item)
2919}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302920
2921// getNniIntfID gets nni intf id from the flow classifier/action
2922func getNniIntfID(classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
2923
2924 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
2925 if portType == voltha.Port_PON_OLT {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002926 intfID, err := IntfIDFromNniPortNum(action[Output].(uint32))
2927 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002928 logger.Debugw("invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002929 log.Fields{
2930 "port-number": action[Output].(uint32),
2931 "error": err})
2932 return uint32(0), err
2933 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002934 logger.Debugw("output Nni IntfID is", log.Fields{"intfid": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302935 return intfID, nil
2936 } else if portType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002937 intfID, err := IntfIDFromNniPortNum(classifier[InPort].(uint32))
2938 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002939 logger.Debugw("invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002940 log.Fields{
2941 "port-number": action[Output].(uint32),
2942 "error": err})
2943 return uint32(0), err
2944 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002945 logger.Debugw("input Nni IntfID is", log.Fields{"intfid": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302946 return intfID, nil
2947 }
2948 return uint32(0), nil
2949}
2950
2951// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
npujarec5762e2020-01-01 14:08:48 +05302952func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302953 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort}
2954
2955 f.lockCache.Lock()
2956 defer f.lockCache.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05002957 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302958 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05002959 if lookupGemPort == gemPort {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002960 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 -05002961 log.Fields{"pktinkey": pktInkey, "gem": gemPort})
2962 return
2963 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302964 }
Matt Jeanneret1719a072019-12-20 14:50:14 -05002965 f.packetInGemPort[pktInkey] = gemPort
2966
npujarec5762e2020-01-01 14:08:48 +05302967 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Girish Kumar2ad402b2020-03-20 19:45:12 +00002968 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 +05302969 return
2970}
2971
2972// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05302973func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302974
2975 f.lockCache.Lock()
2976 defer f.lockCache.Unlock()
2977 onugem := f.onuGemInfo[intfID]
2978 for idx, onu := range onugem {
2979 if onu.OnuID == onuID {
2980 for _, uni := range onu.UniPorts {
2981 if uni == portNum {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002982 logger.Debugw("uni already in cache, no need to update cache and kv store",
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302983 log.Fields{"uni": portNum})
2984 return
2985 }
2986 }
2987 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
2988 f.onuGemInfo[intfID] = onugem
2989 }
2990 }
npujarec5762e2020-01-01 14:08:48 +05302991 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302992}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302993
npujarec5762e2020-01-01 14:08:48 +05302994func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
2995 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302996 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002997 logger.Error("Failed to get flowid list per gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302998 return
2999 }
3000 for gem, FlowIDs := range flowIDsList {
3001 gemPK := gemPortKey{intf, uint32(gem)}
3002 f.flowsUsedByGemPort[gemPK] = FlowIDs
3003 }
3004 return
3005}
Esin Karamanccb714b2019-11-29 15:02:06 +00003006
3007//loadInterfaceToMulticastQueueMap reads multicast queues per interface from the KV store
3008//and put them into interfaceToMcastQueueMap.
npujarec5762e2020-01-01 14:08:48 +05303009func (f *OpenOltFlowMgr) loadInterfaceToMulticastQueueMap(ctx context.Context) {
3010 storedMulticastQueueMap, err := f.resourceMgr.GetMcastQueuePerInterfaceMap(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00003011 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00003012 logger.Error("Failed to get pon interface to multicast queue map")
Esin Karamanccb714b2019-11-29 15:02:06 +00003013 return
3014 }
3015 for intf, queueInfo := range storedMulticastQueueMap {
3016 q := queueInfoBrief{
3017 gemPortID: queueInfo[0],
3018 servicePriority: queueInfo[1],
3019 }
3020 f.interfaceToMcastQueueMap[intf] = &q
3021 }
3022}
3023
3024//GetFlowGroupFromKVStore fetches and returns flow group from the KV store. Returns (nil, false, error) if any problem occurs during
3025//fetching the data. Returns (group, true, nil) if the group is fetched and returned successfully.
3026//Returns (nil, false, nil) if the group does not exists in the KV store.
npujarec5762e2020-01-01 14:08:48 +05303027func (f *OpenOltFlowMgr) GetFlowGroupFromKVStore(ctx context.Context, groupID uint32, cached bool) (*ofp.OfpGroupEntry, bool, error) {
3028 exists, groupInfo, err := f.resourceMgr.GetFlowGroupFromKVStore(ctx, groupID, cached)
Esin Karamanccb714b2019-11-29 15:02:06 +00003029 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003030 return nil, false, olterrors.NewErrNotFound("flow-group", log.Fields{"group-id": groupID}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00003031 }
3032 if exists {
3033 return newGroup(groupInfo.GroupID, groupInfo.OutPorts), exists, nil
3034 }
3035 return nil, exists, nil
3036}
3037
3038func newGroup(groupID uint32, outPorts []uint32) *ofp.OfpGroupEntry {
3039 groupDesc := ofp.OfpGroupDesc{
3040 Type: ofp.OfpGroupType_OFPGT_ALL,
3041 GroupId: groupID,
3042 }
3043 groupEntry := ofp.OfpGroupEntry{
3044 Desc: &groupDesc,
3045 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003046 for i := 0; i < len(outPorts); i++ {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003047 var acts []*ofp.OfpAction
Esin Karamanccb714b2019-11-29 15:02:06 +00003048 acts = append(acts, flows.Output(outPorts[i]))
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003049 bucket := ofp.OfpBucket{
3050 Actions: acts,
3051 }
3052 groupDesc.Buckets = append(groupDesc.Buckets, &bucket)
Esin Karamanccb714b2019-11-29 15:02:06 +00003053 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003054 return &groupEntry
3055}