blob: b229f829cf62a3950b07001d04fee7b9057f9030 [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"
manikkaraj kbf256be2019-03-25 00:13:48 +053025 "fmt"
Manikkaraj kb1d51442019-07-23 10:41:02 -040026 "math/big"
Girish Gowdrafae935c2020-02-17 19:21:44 +053027 "strings"
William Kurkian740a09c2019-10-23 17:07:38 -040028 "sync"
Girish Gowdra3d633032019-12-10 16:37:05 +053029 "time"
Manikkaraj kb1d51442019-07-23 10:41:02 -040030
Esin Karamanccb714b2019-11-29 15:02:06 +000031 "github.com/opencord/voltha-lib-go/v3/pkg/flows"
32 "github.com/opencord/voltha-lib-go/v3/pkg/log"
33 tp "github.com/opencord/voltha-lib-go/v3/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080034 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Esin Karamanccb714b2019-11-29 15:02:06 +000035 "github.com/opencord/voltha-protos/v3/go/common"
36 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
37 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
38 openoltpb2 "github.com/opencord/voltha-protos/v3/go/openolt"
39 tp_pb "github.com/opencord/voltha-protos/v3/go/tech_profile"
40 "github.com/opencord/voltha-protos/v3/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040041
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -040042 //deepcopy "github.com/getlantern/deepcopy"
Girish Gowdra3d633032019-12-10 16:37:05 +053043 "github.com/EagleChen/mapmutex"
Thomas Lee S94109f12020-03-03 16:39:29 +053044 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000045 "google.golang.org/grpc/codes"
46 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053047)
48
49const (
50 // Flow categories
manikkaraj kbf256be2019-03-25 00:13:48 +053051
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070052 //HsiaFlow flow category
53 HsiaFlow = "HSIA_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053054
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070055 //EapolFlow flow category
56 EapolFlow = "EAPOL_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053057
Manikkaraj kb1d51442019-07-23 10:41:02 -040058 //DhcpFlow flow category
59 DhcpFlow = "DHCP_FLOW"
60
Esin Karamanccb714b2019-11-29 15:02:06 +000061 //MulticastFlow flow category
62 MulticastFlow = "MULTICAST_FLOW"
63
Esin Karamanae41e2b2019-12-17 18:13:13 +000064 //IgmpFlow flow category
65 IgmpFlow = "IGMP_FLOW"
66
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070067 //IPProtoDhcp flow category
68 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053069
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070070 //IPProtoIgmp flow category
71 IPProtoIgmp = 2
72
73 //EapEthType eapethtype value
74 EapEthType = 0x888e
75 //LldpEthType lldp ethtype value
76 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000077 //IPv4EthType IPv4 ethernet type value
78 IPv4EthType = 0x800
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070079
80 //IgmpProto proto value
81 IgmpProto = 2
manikkaraj kbf256be2019-03-25 00:13:48 +053082
Andrea Campanella7acc0b92020-02-14 09:20:49 +010083 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
84 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040085
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070086 //DefaultMgmtVlan default vlan value
87 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053088
manikkaraj kbf256be2019-03-25 00:13:48 +053089 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070090
David K. Bainbridge82efc492019-09-04 09:57:11 -070091 //Upstream constant
92 Upstream = "upstream"
93 //Downstream constant
94 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000095 //Multicast constant
96 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070097 //PacketTagType constant
98 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070099 //Untagged constant
100 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700101 //SingleTag constant
102 SingleTag = "single_tag"
103 //DoubleTag constant
104 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +0530105
106 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700107
108 //EthType constant
109 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +0000110 //EthDst constant
111 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700112 //TPID constant
113 TPID = "tpid"
114 //IPProto constant
115 IPProto = "ip_proto"
116 //InPort constant
117 InPort = "in_port"
118 //VlanVid constant
119 VlanVid = "vlan_vid"
120 //VlanPcp constant
121 VlanPcp = "vlan_pcp"
122
123 //UDPDst constant
124 UDPDst = "udp_dst"
125 //UDPSrc constant
126 UDPSrc = "udp_src"
127 //Ipv4Dst constant
128 Ipv4Dst = "ipv4_dst"
129 //Ipv4Src constant
130 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700131 //Metadata constant
132 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700133 //TunnelID constant
134 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700135 //Output constant
136 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000137 //GroupID constant
138 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700139 // Actions
140
141 //PopVlan constant
142 PopVlan = "pop_vlan"
143 //PushVlan constant
144 PushVlan = "push_vlan"
145 //TrapToHost constant
146 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400147 //MaxMeterBand constant
148 MaxMeterBand = 2
149 //VlanPCPMask contant
150 VlanPCPMask = 0xFF
151 //VlanvIDMask constant
152 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000153 //IntfID constant
154 IntfID = "intfId"
155 //OnuID constant
156 OnuID = "onuId"
157 //UniID constant
158 UniID = "uniId"
159 //PortNo constant
160 PortNo = "portNo"
161 //AllocID constant
162 AllocID = "allocId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000163
164 //NoneOnuID constant
165 NoneOnuID = -1
166 //NoneUniID constant
167 NoneUniID = -1
168 //NoneGemPortID constant
169 NoneGemPortID = -1
Girish Gowdrafae935c2020-02-17 19:21:44 +0530170
171 // BinaryStringPrefix is binary string prefix
172 BinaryStringPrefix = "0b"
173 // BinaryBit1 is binary bit 1 expressed as a character
174 BinaryBit1 = '1'
manikkaraj kbf256be2019-03-25 00:13:48 +0530175)
176
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400177type gemPortKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700178 intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400179 gemPort uint32
180}
181
Girish Gowdra3d633032019-12-10 16:37:05 +0530182type pendingFlowDeleteKey struct {
183 intfID uint32
184 onuID uint32
185 uniID uint32
186}
187
188type tpLockKey struct {
189 intfID uint32
190 onuID uint32
191 uniID uint32
192}
193
Gamze Abakafee36392019-10-03 11:17:24 +0000194type schedQueue struct {
195 direction tp_pb.Direction
196 intfID uint32
197 onuID uint32
198 uniID uint32
199 tpID uint32
200 uniPort uint32
201 tpInst *tp.TechProfile
202 meterID uint32
203 flowMetadata *voltha.FlowMetadata
204}
205
Esin Karamanccb714b2019-11-29 15:02:06 +0000206type queueInfoBrief struct {
207 gemPortID uint32
208 servicePriority uint32
209}
210
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700211//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530212type OpenOltFlowMgr struct {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000213 techprofile map[uint32]tp.TechProfileIf
Gamze Abakafee36392019-10-03 11:17:24 +0000214 deviceHandler *DeviceHandler
215 resourceMgr *rsrcMgr.OpenOltResourceMgr
Gamze Abakafee36392019-10-03 11:17:24 +0000216 onuIdsLock sync.RWMutex
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530217 flowsUsedByGemPort map[gemPortKey][]uint32 //gem port id to flow ids
218 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
219 onuGemInfo map[uint32][]rsrcMgr.OnuGemInfo //onu, gem and uni info local cache
220 lockCache sync.RWMutex
Girish Gowdra3d633032019-12-10 16:37:05 +0530221 pendingFlowDelete sync.Map
222 // The mapmutex.Mutex can be fine tuned to use mapmutex.NewCustomizedMapMutex
Esin Karamanccb714b2019-11-29 15:02:06 +0000223 perUserFlowHandleLock *mapmutex.Mutex
224 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 +0530225}
226
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700227//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
npujarec5762e2020-01-01 14:08:48 +0530228func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
manikkaraj kbf256be2019-03-25 00:13:48 +0530229 log.Info("Initializing flow manager")
230 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530231 var err error
232 var idx uint32
233
manikkaraj kbf256be2019-03-25 00:13:48 +0530234 flowMgr.deviceHandler = dh
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530235 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000236 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530237 if err = flowMgr.populateTechProfilePerPonPort(); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000238 log.Errorw("Error while populating tech profile mgr", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530239 return nil
240 }
William Kurkian740a09c2019-10-23 17:07:38 -0400241 flowMgr.onuIdsLock = sync.RWMutex{}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530242 flowMgr.flowsUsedByGemPort = make(map[gemPortKey][]uint32)
243 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
244 flowMgr.onuGemInfo = make(map[uint32][]rsrcMgr.OnuGemInfo)
245 ponPorts := rMgr.DevInfo.GetPonPorts()
246 //Load the onugem info cache from kv store on flowmanager start
247 for idx = 0; idx < ponPorts; idx++ {
npujarec5762e2020-01-01 14:08:48 +0530248 if flowMgr.onuGemInfo[idx], err = rMgr.GetOnuGemInfo(ctx, idx); err != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530249 log.Error("Failed to load onu gem info cache")
250 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530251 //Load flowID list per gem map per interface from the kvstore.
npujarec5762e2020-01-01 14:08:48 +0530252 flowMgr.loadFlowIDlistForGem(ctx, idx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530253 }
254 flowMgr.lockCache = sync.RWMutex{}
Girish Gowdra3d633032019-12-10 16:37:05 +0530255 flowMgr.pendingFlowDelete = sync.Map{}
256 flowMgr.perUserFlowHandleLock = mapmutex.NewMapMutex()
Esin Karamanccb714b2019-11-29 15:02:06 +0000257 flowMgr.interfaceToMcastQueueMap = make(map[uint32]*queueInfoBrief)
258 //load interface to multicast queue map from kv store
npujarec5762e2020-01-01 14:08:48 +0530259 flowMgr.loadInterfaceToMulticastQueueMap(ctx)
manikkaraj kbf256be2019-03-25 00:13:48 +0530260 log.Info("Initialization of flow manager success!!")
261 return &flowMgr
262}
263
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700264func (f *OpenOltFlowMgr) generateStoredFlowID(flowID uint32, direction string) (uint64, error) {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700265 if direction == Upstream {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400266 log.Debug("upstream flow, shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700267 return 0x1<<15 | uint64(flowID), nil
David K. Bainbridge82efc492019-09-04 09:57:11 -0700268 } else if direction == Downstream {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400269 log.Debug("downstream flow, not shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700270 return uint64(flowID), nil
Esin Karamanccb714b2019-11-29 15:02:06 +0000271 } else if direction == Multicast {
272 log.Debug("multicast flow, shifting id")
273 return 0x2<<15 | uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400274 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530275 return 0, olterrors.NewErrInvalidValue(log.Fields{"direction": direction}, nil).Log()
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400276 }
277}
278
npujarec5762e2020-01-01 14:08:48 +0530279func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400280 log.Debug("Registering Flow for Device ", log.Fields{"flow": flowFromCore},
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700281 log.Fields{"device": f.deviceHandler.deviceID})
Gamze Abakafee36392019-10-03 11:17:24 +0000282 gemPK := gemPortKey{uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId)}
283 flowIDList, ok := f.flowsUsedByGemPort[gemPK]
284 if !ok {
285 flowIDList = []uint32{deviceFlow.FlowId}
286 }
287 flowIDList = appendUnique(flowIDList, deviceFlow.FlowId)
288 f.flowsUsedByGemPort[gemPK] = flowIDList
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530289 // update the flowids for a gem to the KVstore
npujarec5762e2020-01-01 14:08:48 +0530290 f.resourceMgr.UpdateFlowIDsForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400291}
292
npujarec5762e2020-01-01 14:08:48 +0530293func (f *OpenOltFlowMgr) divideAndAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000294 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
295 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) {
Gamze Abakafee36392019-10-03 11:17:24 +0000296 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530297 var gemPorts []uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400298 var TpInst *tp.TechProfile
manikkaraj kbf256be2019-03-25 00:13:48 +0530299
Manikkaraj kb1d51442019-07-23 10:41:02 -0400300 log.Infow("Dividing flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "portNo": portNo,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000301 "classifier": classifierInfo, "action": actionInfo, "UsMeterID": UsMeterID, "DsMeterID": DsMeterID, "TpID": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400302 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
303 // is because the flow is an NNI flow and there would be no onu resources associated with it
304 // TODO: properly deal with NNI flows
Manikkaraj kb1d51442019-07-23 10:41:02 -0400305 if onuID <= 0 {
Matt Jeanneret77199612019-07-26 18:08:35 -0400306 log.Errorw("No onu id for flow", log.Fields{"portNo": portNo, "classifer": classifierInfo, "action": actionInfo})
manikkaraj kbf256be2019-03-25 00:13:48 +0530307 return
308 }
309
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530310 uni := getUniPortPath(intfID, int32(onuID), int32(uniID))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400311 log.Debugw("Uni port name", log.Fields{"uni": uni})
Girish Gowdra3d633032019-12-10 16:37:05 +0530312
313 tpLockMapKey := tpLockKey{intfID, onuID, uniID}
314 if f.perUserFlowHandleLock.TryLock(tpLockMapKey) {
npujarec5762e2020-01-01 14:08:48 +0530315 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +0530316 if allocID == 0 || gemPorts == nil || TpInst == nil {
317 log.Error("alloc-id-gem-ports-tp-unavailable")
318 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
319 return
320 }
321 args := make(map[string]uint32)
322 args[IntfID] = intfID
323 args[OnuID] = onuID
324 args[UniID] = uniID
325 args[PortNo] = portNo
326 args[AllocID] = allocID
327
328 /* Flows can be added specific to gemport if p-bits are received.
329 * If no pbit mentioned then adding flows for all gemports
330 */
npujarec5762e2020-01-01 14:08:48 +0530331 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
Girish Gowdra3d633032019-12-10 16:37:05 +0530332 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
333 } else {
334 log.Errorw("failed to acquire per user flow handle lock",
335 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400336 return
337 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530338}
339
salmansiddiqui7ac62132019-08-22 03:58:50 +0000340// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530341func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400342
Gamze Abakafee36392019-10-03 11:17:24 +0000343 log.Debugw("CreateSchedulerQueues", log.Fields{"Dir": sq.direction, "IntfID": sq.intfID,
344 "OnuID": sq.onuID, "UniID": sq.uniID, "TpID": sq.tpID, "MeterID": sq.meterID,
345 "TpInst": sq.tpInst, "flowMetadata": sq.flowMetadata})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400346
Gamze Abakafee36392019-10-03 11:17:24 +0000347 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000348 if err != nil {
349 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400350 }
351
352 /* Lets make a simple assumption that if the meter-id is present on the KV store,
353 * then the scheduler and queues configuration is applied on the OLT device
354 * in the given direction.
355 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000356
Manikkaraj kb1d51442019-07-23 10:41:02 -0400357 var SchedCfg *tp_pb.SchedulerConfig
npujarec5762e2020-01-01 14:08:48 +0530358 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400359 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000360 return olterrors.NewErrNotFound("meter", log.Fields{"intfId": sq.intfID, "onuId": sq.onuID, "uniId": sq.uniID}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400361 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000362
Manikkaraj kb1d51442019-07-23 10:41:02 -0400363 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000364 if KvStoreMeter.MeterId == sq.meterID {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400365 log.Debug("Scheduler already created for upstream")
366 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400367 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530368 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800369 "unsupported": "meter-id",
370 "kv-store-meter-id": KvStoreMeter.MeterId,
Girish Kumarf26e4882020-03-05 06:49:10 +0000371 "meter-id-in-flow": sq.meterID}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400372 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000373
Gamze Abakafee36392019-10-03 11:17:24 +0000374 log.Debugw("Meter-does-not-exist-Creating-new", log.Fields{"MeterID": sq.meterID, "Direction": Direction})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000375
Gamze Abakafee36392019-10-03 11:17:24 +0000376 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000377 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Gamze Abakafee36392019-10-03 11:17:24 +0000378 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000379 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400380 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000381
382 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000383 return olterrors.NewErrNotFound("scheduler-config", log.Fields{"IntfID": sq.intfID, "Direction": sq.direction, "tpInst": sq.tpInst}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000384 }
385
Manikkaraj kb1d51442019-07-23 10:41:02 -0400386 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000387 if sq.flowMetadata != nil {
388 for _, meter := range sq.flowMetadata.Meters {
389 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400390 meterConfig = meter
391 log.Debugw("Found-meter-config-from-flowmetadata", log.Fields{"meterConfig": meterConfig})
392 break
393 }
394 }
395 } else {
396 log.Error("Flow-metadata-is-not-present-in-flow")
397 }
398 if meterConfig == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530399 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800400 "reason": "Could-not-get-meterbands-from-flowMetadata",
401 "flow-metadata": sq.flowMetadata,
Girish Kumarf26e4882020-03-05 06:49:10 +0000402 "meter-id": sq.meterID}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400403 } else if len(meterConfig.Bands) < MaxMeterBand {
Gamze Abakafee36392019-10-03 11:17:24 +0000404 log.Errorw("Invalid-number-of-bands-in-meter", log.Fields{"Bands": meterConfig.Bands, "MeterID": sq.meterID})
Thomas Lee S94109f12020-03-03 16:39:29 +0530405 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800406 "reason": "Invalid-number-of-bands-in-meter",
407 "meterband-count": len(meterConfig.Bands),
408 "metabands": meterConfig.Bands,
Girish Kumarf26e4882020-03-05 06:49:10 +0000409 "meter-id": sq.meterID}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400410 }
411 cir := meterConfig.Bands[0].Rate
412 cbs := meterConfig.Bands[0].BurstSize
413 eir := meterConfig.Bands[1].Rate
414 ebs := meterConfig.Bands[1].BurstSize
415 pir := cir + eir
416 pbs := cbs + ebs
417 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
418
Gamze Abakafee36392019-10-03 11:17:24 +0000419 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Manikkaraj kb1d51442019-07-23 10:41:02 -0400420
npujarec5762e2020-01-01 14:08:48 +0530421 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficShaping, TrafficSched); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000422 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 -0400423 }
424
salmansiddiqui7ac62132019-08-22 03:58:50 +0000425 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400426 * store the meter id on the KV store, for further reference.
427 */
npujarec5762e2020-01-01 14:08:48 +0530428 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 +0000429 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 -0400430 }
431 log.Debugw("updated-meter-info into KV store successfully", log.Fields{"Direction": Direction,
432 "Meter": meterConfig})
433 return nil
434}
435
npujarec5762e2020-01-01 14:08:48 +0530436func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficShaping *tp_pb.TrafficShapingInfo, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000437
438 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
439
440 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000441 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 +0000442 }
443
444 log.Debugw("Sending Traffic scheduler create to device", log.Fields{"Direction": sq.direction, "TrafficScheds": TrafficSched})
npujarec5762e2020-01-01 14:08:48 +0530445 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000446 IntfId: sq.intfID, OnuId: sq.onuID,
447 UniId: sq.uniID, PortNo: sq.uniPort,
448 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000449 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000450 }
451
452 // On receiving the CreateTrafficQueues request, the driver should create corresponding
453 // downstream queues.
454 log.Debugw("Sending Traffic Queues create to device", log.Fields{"Direction": sq.direction, "TrafficQueues": trafficQueues})
npujarec5762e2020-01-01 14:08:48 +0530455 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000456 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
457 UniId: sq.uniID, PortNo: sq.uniPort,
458 TrafficQueues: trafficQueues}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000459 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"TrafficQueues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000460 }
461
Esin Karamanccb714b2019-11-29 15:02:06 +0000462 if sq.direction == tp_pb.Direction_DOWNSTREAM {
463 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(sq.tpInst)
464 if len(multicastTrafficQueues) > 0 {
465 if _, present := f.interfaceToMcastQueueMap[sq.intfID]; !present {
466 //assumed that there is only one queue per PON for the multicast service
467 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
468 //just put it in interfaceToMcastQueueMap to use for building group members
469 multicastQueuePerPonPort := multicastTrafficQueues[0]
470 f.interfaceToMcastQueueMap[sq.intfID] = &queueInfoBrief{
471 gemPortID: multicastQueuePerPonPort.GemportId,
472 servicePriority: multicastQueuePerPonPort.Priority,
473 }
474 //also store the queue info in kv store
npujarec5762e2020-01-01 14:08:48 +0530475 f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID,
Esin Karamanccb714b2019-11-29 15:02:06 +0000476 multicastQueuePerPonPort.GemportId,
477 multicastQueuePerPonPort.Priority)
478 }
479 }
480 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000481 return nil
482}
483
salmansiddiqui7ac62132019-08-22 03:58:50 +0000484// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530485func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400486
487 var Direction string
488 var SchedCfg *tp_pb.SchedulerConfig
489 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000490 log.Debugw("Removing schedulers and Queues in OLT", log.Fields{"Direction": sq.direction, "IntfID": sq.intfID,
491 "OnuID": sq.onuID, "UniID": sq.uniID, "UniPort": sq.uniPort})
492 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000493 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400494 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000495 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000496 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400497 Direction = "downstream"
498 }
499
Girish Kumar8f73fe02019-12-09 13:19:37 +0000500 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000501 return olterrors.NewErrNotFound("scheduler-config", log.Fields{"IntID": sq.intfID, "Direction": sq.direction}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000502 }
503
npujarec5762e2020-01-01 14:08:48 +0530504 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400505 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000506 return olterrors.NewErrNotFound("meter", log.Fields{"onuID": sq.onuID}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400507 }
508 if KVStoreMeter == nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000509 log.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 -0400510 return nil
511 }
512 cir := KVStoreMeter.Bands[0].Rate
513 cbs := KVStoreMeter.Bands[0].BurstSize
514 eir := KVStoreMeter.Bands[1].Rate
515 ebs := KVStoreMeter.Bands[1].BurstSize
516 pir := cir + eir
517 pbs := cbs + ebs
518
519 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
520
Gamze Abakafee36392019-10-03 11:17:24 +0000521 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Girish Kumar8f73fe02019-12-09 13:19:37 +0000522
523 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
524 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000525 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 +0000526 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400527
npujarec5762e2020-01-01 14:08:48 +0530528 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000529 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
530 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400531 TrafficQueues: TrafficQueues}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000532 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
533 log.Fields{"intfID": sq.intfID, "TrafficQueues": TrafficQueues}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400534 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000535 log.Debug("Removed traffic queues successfully")
npujarec5762e2020-01-01 14:08:48 +0530536 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000537 IntfId: sq.intfID, OnuId: sq.onuID,
538 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400539 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000540 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
541 log.Fields{"intfID": sq.intfID, "TrafficSchedulers": TrafficSched}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400542 }
543
salmansiddiqui7ac62132019-08-22 03:58:50 +0000544 log.Debug("Removed traffic schedulers successfully")
545
546 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400547 * delete the meter id on the KV store.
548 */
npujarec5762e2020-01-01 14:08:48 +0530549 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400550 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000551 return olterrors.NewErrAdapter("unable-to-remove-meter", log.Fields{"onu": sq.onuID, "meter": KVStoreMeter.MeterId}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400552 }
553 log.Debugw("Removed-meter-from-KV-store successfully", log.Fields{"MeterId": KVStoreMeter.MeterId, "dir": Direction})
554 return err
555}
556
Gamze Abakafee36392019-10-03 11:17:24 +0000557// This function allocates tconts and GEM ports for an ONU
npujarec5762e2020-01-01 14:08:48 +0530558func (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 +0000559 var allocIDs []uint32
560 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530561 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530562 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000563 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000564
npujarec5762e2020-01-01 14:08:48 +0530565 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
566 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400567
568 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530569
570 log.Infow("creating-new-tcont-and-gem", log.Fields{"pon": intfID, "onu": onuID, "uni": uniID})
571
Manikkaraj kb1d51442019-07-23 10:41:02 -0400572 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530573 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000574 if techProfileInstance == nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530575 log.Infow("tp-instance-not-found--creating-new", log.Fields{"path": tpPath})
npujarec5762e2020-01-01 14:08:48 +0530576 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000577 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530578 // This should not happen, something wrong in KV backend transaction
Girish Kumar8f73fe02019-12-09 13:19:37 +0000579 log.Errorw("tp-instance-create-failed", log.Fields{"error": err, "tpID": TpID})
Gamze Abakafee36392019-10-03 11:17:24 +0000580 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530581 }
npujarec5762e2020-01-01 14:08:48 +0530582 f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530583 } else {
584 log.Debugw("Tech-profile-instance-already-exist-for-given port-name", log.Fields{"uni": uni})
Girish Gowdra3d633032019-12-10 16:37:05 +0530585 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530586 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400587 if UsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000588 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
589 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
npujarec5762e2020-01-01 14:08:48 +0530590 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400591 log.Errorw("CreateSchedulerQueues Failed-upstream", log.Fields{"error": err, "meterID": UsMeterID})
Gamze Abakafee36392019-10-03 11:17:24 +0000592 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400593 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530594 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400595 if DsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000596 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
597 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
npujarec5762e2020-01-01 14:08:48 +0530598 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400599 log.Errorw("CreateSchedulerQueues Failed-downstream", log.Fields{"error": err, "meterID": DsMeterID})
Gamze Abakafee36392019-10-03 11:17:24 +0000600 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400601 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530602 }
Gamze Abakafee36392019-10-03 11:17:24 +0000603
604 allocID := techProfileInstance.UsScheduler.AllocID
Gamze Abakafee36392019-10-03 11:17:24 +0000605 for _, gem := range techProfileInstance.UpstreamGemPortAttributeList {
Gamze Abakafee36392019-10-03 11:17:24 +0000606 gemPortIDs = append(gemPortIDs, gem.GemportID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400607 }
Gamze Abakafee36392019-10-03 11:17:24 +0000608
Girish Gowdra3d633032019-12-10 16:37:05 +0530609 if tpInstanceExists {
610 return allocID, gemPortIDs, techProfileInstance
611 }
612
613 allocIDs = appendUnique(allocIDs, allocID)
614 for _, gemPortID := range gemPortIDs {
615 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
616 }
617
Gamze Abakafee36392019-10-03 11:17:24 +0000618 log.Debugw("Allocated Tcont and GEM ports", log.Fields{"allocIDs": allocIDs, "gemports": allgemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530619 // Send Tconts and GEM ports to KV store
npujarec5762e2020-01-01 14:08:48 +0530620 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000621 return allocID, gemPortIDs, techProfileInstance
manikkaraj kbf256be2019-03-25 00:13:48 +0530622}
623
npujarec5762e2020-01-01 14:08:48 +0530624func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530625
626 log.Debugw("Storing allocated Tconts and GEM ports into KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700627 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "allocID": allocID, "gemPortIDs": gemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530628 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530629 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530630 log.Error("Errow while uploading allocID to KV store")
631 }
npujarec5762e2020-01-01 14:08:48 +0530632 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530633 log.Error("Errow while uploading GEMports to KV store")
634 }
npujarec5762e2020-01-01 14:08:48 +0530635 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530636 log.Error("Errow while uploading gemtopon map to KV store")
637 }
638 log.Debug("Stored tconts and GEM into KV store successfully")
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400639 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530640 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400641 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530642}
643
644func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000645 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530646 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000647 for _, intfID := range techRange.IntfIds {
648 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400649 tpCount++
salmansiddiqui7ac62132019-08-22 03:58:50 +0000650 log.Debugw("Init tech profile done", log.Fields{"intfID": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530651 }
652 }
653 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400654 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530655 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800656 "reason": "TP count does not match number of PON ports",
657 "tech-profile-count": tpCount,
Girish Kumarf26e4882020-03-05 06:49:10 +0000658 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts()}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530659 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400660 log.Infow("Populated techprofile for ponports successfully",
661 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
manikkaraj kbf256be2019-03-25 00:13:48 +0530662 return nil
663}
664
npujarec5762e2020-01-01 14:08:48 +0530665func (f *OpenOltFlowMgr) addUpstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530666 portNo uint32, uplinkClassifier map[string]interface{},
667 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800668 allocID uint32, gemportID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700669 uplinkClassifier[PacketTagType] = SingleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530670 log.Debugw("Adding upstream data flow", log.Fields{"uplinkClassifier": uplinkClassifier, "uplinkAction": uplinkAction})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800671 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700672 Upstream, logicalFlow, allocID, gemportID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530673 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530674}
675
npujarec5762e2020-01-01 14:08:48 +0530676func (f *OpenOltFlowMgr) addDownstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530677 portNo uint32, downlinkClassifier map[string]interface{},
678 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800679 allocID uint32, gemportID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700680 downlinkClassifier[PacketTagType] = DoubleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530681 log.Debugw("Adding downstream data flow", log.Fields{"downlinkClassifier": downlinkClassifier,
682 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400683 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
684 if vlan, exists := downlinkClassifier[VlanVid]; exists {
685 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700686 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Manikkaraj kb1d51442019-07-23 10:41:02 -0400687 if uint32(metadata.(uint64)) == MkUniPortNum(intfID, onuID, uniID) {
688 log.Infow("Ignoring DL trap device flow from core", log.Fields{"flow": logicalFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800689 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400690 }
691 }
692 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530693 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400694
Manikkaraj k884c1242019-04-11 16:26:42 +0530695 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700696 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400697 // vlan_vid is a uint32. must be type asserted as such or conversion fails
698 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530699 if ok {
700 downlinkAction[VlanVid] = dlClVid & 0xfff
701 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530702 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800703 "reason": "failed to convert VLANID classifier",
704 "vlan-id": VlanVid}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530705 }
706
David K. Bainbridge794735f2020-02-11 21:01:37 -0800707 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700708 Downstream, logicalFlow, allocID, gemportID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530709}
710
npujarec5762e2020-01-01 14:08:48 +0530711func (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 +0530712 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800713 allocID uint32, gemPortID uint32) error {
Manikkaraj k884c1242019-04-11 16:26:42 +0530714 /* One of the OLT platform (Broadcom BAL) requires that symmetric
715 flows require the same flow_id to be used across UL and DL.
716 Since HSIA flow is the only symmetric flow currently, we need to
717 re-use the flow_id across both direction. The 'flow_category'
718 takes priority over flow_cookie to find any available HSIA_FLOW
719 id for the ONU.
720 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700721 log.Debugw("Adding HSIA flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "classifier": classifier,
722 "action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530723 "logicalFlow": *logicalFlow})
Girish Gowdrafae935c2020-02-17 19:21:44 +0530724 var vlanPbit uint32 = 0xff // means no pbit
Manikkaraj kb1d51442019-07-23 10:41:02 -0400725 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000726 vlanPbit = classifier[VlanPcp].(uint32)
727 log.Debugw("Found pbit in the flow", log.Fields{"VlanPbit": vlanPbit})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800728 } else {
Girish Gowdrafae935c2020-02-17 19:21:44 +0530729 log.Debugw("pbit-not-found-in-flow", log.Fields{"vlan-pcp": VlanPcp})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400730 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700731 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530732 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800733 log.Debug("flow-already-exists")
734 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530735 }
npujarec5762e2020-01-01 14:08:48 +0530736 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530737 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530738 return olterrors.NewErrNotFound("hsia-flow-id", log.Fields{"direction": direction}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530739 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800740 classifierProto, err := makeOpenOltClassifierField(classifier)
741 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530742 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530743 }
744 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800745 actionProto, err := makeOpenOltActionField(action)
746 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530747 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530748 }
749 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800750 networkIntfID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530751 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530752 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800753 log.Fields{
754 "classifier": classifier,
755 "action": action,
756 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530757 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700758 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
759 OnuId: int32(onuID),
760 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000761 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530762 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700763 AllocId: int32(allocID),
764 NetworkIntfId: int32(networkIntfID),
765 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530766 Classifier: classifierProto,
767 Action: actionProto,
768 Priority: int32(logicalFlow.Priority),
769 Cookie: logicalFlow.Cookie,
770 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800771 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530772 return olterrors.NewErrFlowOp("add", flowID, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530773 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800774 log.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
775 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
776 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
777 flow.OnuId,
778 flow.UniId,
779 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530780 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": flow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800781 }
782 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +0530783}
Esin Karamanae41e2b2019-12-17 18:13:13 +0000784
David K. Bainbridge794735f2020-02-11 21:01:37 -0800785func (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 +0530786
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530787 networkIntfID, err := getNniIntfID(classifier, action)
788 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530789 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800790 "classifier": classifier,
791 "action": action},
792 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530793 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530794
795 // Clear the action map
796 for k := range action {
797 delete(action, k)
798 }
799
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700800 action[TrapToHost] = true
801 classifier[UDPSrc] = uint32(68)
802 classifier[UDPDst] = uint32(67)
803 classifier[PacketTagType] = SingleTag
804 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530805
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700806 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530807 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Girish Gowdra3d633032019-12-10 16:37:05 +0530808 log.Debug("Flow-exists--not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800809 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530810 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530811
David K. Bainbridge794735f2020-02-11 21:01:37 -0800812 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 +0530813
814 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530815 return olterrors.NewErrNotFound("flow", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800816 "interface-id": intfID,
817 "gem-port": gemPortID,
818 "cookie": flowStoreCookie},
819 err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530820 }
821
822 log.Debugw("Creating UL DHCP flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID})
823
David K. Bainbridge794735f2020-02-11 21:01:37 -0800824 classifierProto, err := makeOpenOltClassifierField(classifier)
825 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530826 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530827 }
828 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800829 actionProto, err := makeOpenOltActionField(action)
830 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530831 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530832 }
833
David K. Bainbridge794735f2020-02-11 21:01:37 -0800834 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700835 OnuId: int32(onuID),
836 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530837 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700838 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700839 AllocId: int32(allocID),
840 NetworkIntfId: int32(networkIntfID),
841 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530842 Classifier: classifierProto,
843 Action: actionProto,
844 Priority: int32(logicalFlow.Priority),
845 Cookie: logicalFlow.Cookie,
846 PortNo: portNo}
847
David K. Bainbridge794735f2020-02-11 21:01:37 -0800848 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530849 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800850 }
851 log.Debug("DHCP UL flow added to device successfully")
852 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
853 if err := f.updateFlowInfoToKVStore(ctx, dhcpFlow.AccessIntfId,
854 dhcpFlow.OnuId,
855 dhcpFlow.UniId,
856 dhcpFlow.FlowId, flowsToKVStore); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530857 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId, log.Fields{"flow": dhcpFlow}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530858 }
859
David K. Bainbridge794735f2020-02-11 21:01:37 -0800860 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530861}
862
Esin Karamanae41e2b2019-12-17 18:13:13 +0000863//addIGMPTrapFlow creates IGMP trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +0530864func (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 -0800865 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32) error {
866 return f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, IgmpFlow)
Esin Karamanae41e2b2019-12-17 18:13:13 +0000867}
868
869//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +0530870func (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 -0800871 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, flowType string) error {
Esin Karamanae41e2b2019-12-17 18:13:13 +0000872
873 networkIntfID, err := getNniIntfID(classifier, action)
874 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530875 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800876 "classifier": classifier,
877 "action": action},
878 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000879 }
880
881 // Clear the action map
882 for k := range action {
883 delete(action, k)
884 }
885
886 action[TrapToHost] = true
887 classifier[PacketTagType] = SingleTag
888 delete(classifier, VlanVid)
889
890 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530891 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkIntfID), int32(onuID), int32(uniID), flowStoreCookie); present {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800892 log.Debug("Flow-exists-not-re-adding")
893 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +0000894 }
895
npujarec5762e2020-01-01 14:08:48 +0530896 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 +0000897
898 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530899 return olterrors.NewErrNotFound("flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800900 "interface-id": intfID,
901 "oni-id": onuID,
902 "cookie": flowStoreCookie,
903 "flow-type": flowType},
904 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000905 }
906
907 log.Debugw("Creating upstream trap flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID, "flowType": flowType})
908
David K. Bainbridge794735f2020-02-11 21:01:37 -0800909 classifierProto, err := makeOpenOltClassifierField(classifier)
910 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530911 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000912 }
913 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800914 actionProto, err := makeOpenOltActionField(action)
915 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530916 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000917 }
918
David K. Bainbridge794735f2020-02-11 21:01:37 -0800919 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +0000920 OnuId: int32(onuID),
921 UniId: int32(uniID),
922 FlowId: flowID,
923 FlowType: Upstream,
924 AllocId: int32(allocID),
925 NetworkIntfId: int32(networkIntfID),
926 GemportId: int32(gemPortID),
927 Classifier: classifierProto,
928 Action: actionProto,
929 Priority: int32(logicalFlow.Priority),
930 Cookie: logicalFlow.Cookie,
931 PortNo: portNo}
932
David K. Bainbridge794735f2020-02-11 21:01:37 -0800933 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530934 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": flow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800935 }
936 log.Debugf("%s UL flow added to device successfully", flowType)
Esin Karamanae41e2b2019-12-17 18:13:13 +0000937
David K. Bainbridge794735f2020-02-11 21:01:37 -0800938 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, flowType, flowID, logicalFlow.Id)
939 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
940 flow.OnuId,
941 flow.UniId,
942 flow.FlowId, flowsToKVStore); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530943 return olterrors.NewErrPersistence("update", "flow", flow.FlowId, log.Fields{"flow": flow}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +0000944 }
945
David K. Bainbridge794735f2020-02-11 21:01:37 -0800946 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +0000947}
948
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700949// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Girish Gowdrafae935c2020-02-17 19:21:44 +0530950func (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 Gowdru6a80bbd2019-07-02 07:36:09 -0700951 log.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 +0530952
953 uplinkClassifier := make(map[string]interface{})
954 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +0530955
manikkaraj kbf256be2019-03-25 00:13:48 +0530956 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700957 uplinkClassifier[EthType] = uint32(EapEthType)
958 uplinkClassifier[PacketTagType] = SingleTag
959 uplinkClassifier[VlanVid] = vlanID
manikkaraj kbf256be2019-03-25 00:13:48 +0530960 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700961 uplinkAction[TrapToHost] = true
962 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530963 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800964 log.Debug("Flow-exists-not-re-adding")
965 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530966 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530967 //Add Uplink EAPOL Flow
npujarec5762e2020-01-01 14:08:48 +0530968 uplinkFlowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530969 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530970 return olterrors.NewErrNotFound("flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800971 "interface-id": intfID,
972 "onu-id": onuID,
973 "coookie": flowStoreCookie},
974 err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +0530975 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700976 log.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530977
David K. Bainbridge794735f2020-02-11 21:01:37 -0800978 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
979 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530980 return olterrors.NewErrInvalidValue(log.Fields{"classifier": uplinkClassifier}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +0530981 }
982 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800983 actionProto, err := makeOpenOltActionField(uplinkAction)
984 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530985 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +0530986 }
987 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800988 networkIntfID, err := getNniIntfID(classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530989 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530990 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800991 "classifier": classifier,
992 "action": action},
993 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530994 }
995
David K. Bainbridge794735f2020-02-11 21:01:37 -0800996 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700997 OnuId: int32(onuID),
998 UniId: int32(uniID),
999 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001000 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001001 AllocId: int32(allocID),
1002 NetworkIntfId: int32(networkIntfID),
1003 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301004 Classifier: classifierProto,
1005 Action: actionProto,
1006 Priority: int32(logicalFlow.Priority),
1007 Cookie: logicalFlow.Cookie,
1008 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001009 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301010 return olterrors.NewErrFlowOp("add", uplinkFlowID, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001011 }
1012 log.Debug("EAPOL UL flow added to device successfully")
1013 flowCategory := "EAPOL"
1014 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
1015 if err := f.updateFlowInfoToKVStore(ctx, upstreamFlow.AccessIntfId,
1016 upstreamFlow.OnuId,
1017 upstreamFlow.UniId,
1018 upstreamFlow.FlowId,
1019 /* lowCategory, */
1020 flowsToKVStore); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301021 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId, log.Fields{"flow": upstreamFlow}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301022 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301023
manikkaraj kbf256be2019-03-25 00:13:48 +05301024 log.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001025 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301026}
1027
David K. Bainbridge794735f2020-02-11 21:01:37 -08001028func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001029 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001030
1031 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1032 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1033 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001034 if vlanID != ReservedVlan {
1035 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001036 classifier.OVid = vid
1037 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301038 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001039 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1040 vid := uint32(metadata)
1041 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001042 classifier.IVid = vid
1043 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301044 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301045 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001046 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301047 classifier.OPbits = vlanPcp
1048 } else {
1049 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301050 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001051 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1052 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1053 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1054 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001055 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001056 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1057 classifier.PktTagType = pktTagType
1058
1059 switch pktTagType {
1060 case SingleTag:
1061 case DoubleTag:
1062 case Untagged:
1063 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001064 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301065 }
1066 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001067 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301068}
1069
David K. Bainbridge794735f2020-02-11 21:01:37 -08001070func makeOpenOltActionField(actionInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001071 var actionCmd openoltpb2.ActionCmd
1072 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301073 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001074 if _, ok := actionInfo[PopVlan]; ok {
1075 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301076 action.Cmd.RemoveOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001077 } else if _, ok := actionInfo[PushVlan]; ok {
1078 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301079 action.Cmd.AddOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001080 } else if _, ok := actionInfo[TrapToHost]; ok {
1081 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301082 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001083 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301084 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001085 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301086}
1087
Manikkaraj kb1d51442019-07-23 10:41:02 -04001088func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uni string, TpID uint32) string {
1089 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +05301090}
1091
Gamze Abakafee36392019-10-03 11:17:24 +00001092// DeleteTechProfileInstances removes the tech profile instances from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301093func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, sn string) error {
1094 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001095 uniPortName := fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001096 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301097 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001098 olterrors.NewErrAdapter("delete-tech-profile-failed", nil, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301099 // return err
1100 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001101 }
1102 }
1103 return nil
1104}
1105
1106// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301107func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001108 if uniPortName == "" {
1109 uniPortName = fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1110 }
npujarec5762e2020-01-01 14:08:48 +05301111 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001112 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 -04001113 }
1114 return nil
1115}
1116
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001117func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +05301118 if len(classifier) == 0 { // should never happen
1119 log.Error("Invalid classfier object")
1120 return 0
1121 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301122 log.Debugw("generating flow store cookie", log.Fields{"classifier": classifier, "gemPortID": gemPortID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301123 var jsonData []byte
1124 var flowString string
1125 var err error
1126 // TODO: Do we need to marshall ??
1127 if jsonData, err = json.Marshal(classifier); err != nil {
1128 log.Error("Failed to encode classifier")
1129 return 0
1130 }
1131 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001132 if gemPortID != 0 {
1133 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +05301134 }
1135 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001136 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +05301137 hash := big.NewInt(0)
1138 hash.SetBytes(h.Sum(nil))
Girish Gowdra3d633032019-12-10 16:37:05 +05301139 generatedHash := hash.Uint64()
1140 log.Debugw("hash generated", log.Fields{"hash": generatedHash})
1141 return generatedHash
manikkaraj kbf256be2019-03-25 00:13:48 +05301142}
1143
npujarec5762e2020-01-01 14:08:48 +05301144func (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 +05301145 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001146 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001147 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1148 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1149 */
1150 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001151 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001152 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001153 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001154 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001155 // Get existing flows matching flowid for given subscriber from KV store
npujarec5762e2020-01-01 14:08:48 +05301156 existingFlows := f.resourceMgr.GetFlowIDInfo(ctx, intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001157 if existingFlows != nil {
1158 log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001159 //for _, f := range *existingFlows {
1160 // flows = append(flows, f)
1161 //}
1162 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001163 }
1164 log.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 +05301165 return &flows
1166}
1167
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001168//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
1169// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
1170// var intfId uint32
1171// /* For flows which trap out of the NNI, the AccessIntfId is invalid
1172// (set to -1). In such cases, we need to refer to the NetworkIntfId .
1173// */
1174// if flow.AccessIntfId != -1 {
1175// intfId = uint32(flow.AccessIntfId)
1176// } else {
1177// intfId = uint32(flow.NetworkIntfId)
1178// }
1179// // Get existing flows matching flowid for given subscriber from KV store
1180// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
1181// if existingFlows != nil {
1182// log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
1183// for _, f := range *existingFlows {
1184// flows = append(flows, f)
1185// }
1186// }
1187// log.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
1188// return &flows
1189//}
1190
npujarec5762e2020-01-01 14:08:48 +05301191func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(ctx context.Context, intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
manikkaraj k17652a72019-05-06 09:06:36 -04001192 log.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
npujarec5762e2020-01-01 14:08:48 +05301193 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, intfID, onuID, uniID, flowID, flows); err != nil {
manikkaraj k17652a72019-05-06 09:06:36 -04001194 log.Debug("Error while Storing flow into KV store")
1195 return err
1196 }
1197 log.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +05301198 return nil
1199}
1200
David K. Bainbridge794735f2020-02-11 21:01:37 -08001201func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001202
1203 var intfID uint32
1204 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1205 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1206 */
1207 if deviceFlow.AccessIntfId != -1 {
1208 intfID = uint32(deviceFlow.AccessIntfId)
1209 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001210 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001211 intfID = uint32(deviceFlow.NetworkIntfId)
1212 }
1213
manikkaraj kbf256be2019-03-25 00:13:48 +05301214 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1215 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001216
1217 st, _ := status.FromError(err)
1218 if st.Code() == codes.AlreadyExists {
Gamze Abakafee36392019-10-03 11:17:24 +00001219 log.Debug("Flow already exists", log.Fields{"err": err, "deviceFlow": deviceFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001220 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301221 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001222
1223 if err != nil {
1224 log.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": deviceFlow})
npujarec5762e2020-01-01 14:08:48 +05301225 f.resourceMgr.FreeFlowID(ctx, intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001226 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001227 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301228 if deviceFlow.GemportId != -1 {
1229 // No need to register the flow if it is a trap on nni flow.
npujarec5762e2020-01-01 14:08:48 +05301230 f.registerFlow(ctx, logicalFlow, deviceFlow)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301231 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301232 log.Debugw("Flow added to device successfully ", log.Fields{"flow": *deviceFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001233 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001234}
1235
David K. Bainbridge794735f2020-02-11 21:01:37 -08001236func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001237 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1238 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1239 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001240 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
1241 log.Warnw("Can not remove flow from device since it's unreachable", log.Fields{"err": err, "deviceFlow": deviceFlow})
1242 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001243 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001244 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001245 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001246
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001247 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001248 log.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001249 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301250}
1251
1252/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1253 //update core flows_proxy : flows_proxy.update('/', flows)
1254}
1255
1256func generateStoredId(flowId uint32, direction string)uint32{
1257
David K. Bainbridge82efc492019-09-04 09:57:11 -07001258 if direction == Upstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301259 log.Debug("Upstream flow shifting flowid")
1260 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001261 }else if direction == Downstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301262 log.Debug("Downstream flow not shifting flowid")
1263 return flowId
1264 }else{
1265 log.Errorw("Unrecognized direction",log.Fields{"direction": direction})
1266 return flowId
1267 }
1268}
1269
1270*/
1271
David K. Bainbridge794735f2020-02-11 21:01:37 -08001272func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001273
1274 classifierInfo := make(map[string]interface{})
1275 actionInfo := make(map[string]interface{})
1276
1277 classifierInfo[EthType] = uint32(LldpEthType)
1278 classifierInfo[PacketTagType] = Untagged
1279 actionInfo[TrapToHost] = true
1280
1281 // LLDP flow is installed to trap LLDP packets on the NNI port.
1282 // We manage flow_id resource pool on per PON port basis.
1283 // Since this situation is tricky, as a hack, we pass the NNI port
1284 // index (network_intf_id) as PON port Index for the flow_id resource
1285 // pool. Also, there is no ONU Id available for trapping LLDP packets
1286 // on NNI port, use onu_id as -1 (invalid)
1287 // ****************** CAVEAT *******************
1288 // This logic works if the NNI Port Id falls within the same valid
1289 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1290 // we need to have a re-look at this.
1291 // *********************************************
1292
1293 var onuID = -1
1294 var uniID = -1
1295 var gemPortID = -1
1296
David K. Bainbridge794735f2020-02-11 21:01:37 -08001297 networkInterfaceID, err := IntfIDFromNniPortNum(portNo)
1298 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301299 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001300 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001301 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05301302 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Humera Kouser94d7a842019-08-25 19:04:32 -04001303 log.Debug("Flow-exists--not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001304 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001305 }
npujarec5762e2020-01-01 14:08:48 +05301306 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001307
1308 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301309 return olterrors.NewErrNotFound("flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001310 "interface-id": networkInterfaceID,
1311 "onu-id": onuID,
1312 "uni-id": uniID,
1313 "gem-port-id": gemPortID,
1314 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00001315 err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001316 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001317 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1318 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001319 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001320 }
1321 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001322 actionProto, err := makeOpenOltActionField(actionInfo)
1323 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001324 return olterrors.NewErrInvalidValue(log.Fields{"action": actionInfo}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001325 }
1326 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
1327
1328 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1329 OnuId: int32(onuID), // OnuId not required
1330 UniId: int32(uniID), // UniId not used
1331 FlowId: flowID,
1332 FlowType: Downstream,
1333 NetworkIntfId: int32(networkInterfaceID),
1334 GemportId: int32(gemPortID),
1335 Classifier: classifierProto,
1336 Action: actionProto,
1337 Priority: int32(flow.Priority),
1338 Cookie: flow.Cookie,
1339 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001340 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001341 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001342 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001343 log.Debug("LLDP trap on NNI flow added to device successfully")
1344 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, flow.Id)
1345 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
1346 int32(onuID),
1347 int32(uniID),
1348 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001349 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001350 }
1351 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301352}
1353
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301354func getUniPortPath(intfID uint32, onuID int32, uniID int32) string {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001355 return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1356}
1357
1358//getOnuChildDevice to fetch onu
1359func (f *OpenOltFlowMgr) getOnuChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
1360 log.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
1361 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001362 onuDevice, err := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
1363 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301364 return nil, olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001365 "interface-id": parentPortNo,
1366 "onu-id": onuID},
Girish Kumarf26e4882020-03-05 06:49:10 +00001367 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301368 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301369 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1370 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301371}
1372
1373func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001374 log.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301375 return nil
1376}
1377
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001378func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
1379 log.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301380}
1381
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001382func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001383 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001384 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001385 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001386 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001387}
1388
Girish Gowdra6b130582019-11-20 16:45:20 +05301389func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1390 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
1391 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001392 return olterrors.NewErrNotFound("onu-child-device", log.Fields{"onuId": onuID, "intfID": intfID}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301393 }
1394
1395 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
1396 log.Debugw("sending gem port delete to openonu adapter", log.Fields{"msg": *delGemPortMsg})
1397 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1398 delGemPortMsg,
1399 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
1400 f.deviceHandler.deviceType,
1401 onuDevice.Type,
1402 onuDevice.Id,
1403 onuDevice.ProxyAddress.DeviceId, ""); sendErr != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001404 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
Girish Gowdra6b130582019-11-20 16:45:20 +05301405 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001406 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301407 }
1408 log.Debugw("success sending del gem port to onu adapter", log.Fields{"msg": delGemPortMsg})
1409 return nil
1410}
1411
1412func (f *OpenOltFlowMgr) sendDeleteTcontToChild(intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1413 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
1414 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001415 return olterrors.NewErrNotFound("onu-child-device", log.Fields{"onuId": onuID, "intfID": intfID}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301416 }
1417
1418 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
1419 log.Debugw("sending tcont delete to openonu adapter", log.Fields{"msg": *delTcontMsg})
1420 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1421 delTcontMsg,
1422 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
1423 f.deviceHandler.deviceType,
1424 onuDevice.Type,
1425 onuDevice.Id,
1426 onuDevice.ProxyAddress.DeviceId, ""); sendErr != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001427 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
Girish Gowdra6b130582019-11-20 16:45:20 +05301428 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001429 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301430 }
1431 log.Debugw("success sending del tcont to onu adapter", log.Fields{"msg": delTcontMsg})
1432 return nil
1433}
1434
Girish Gowdra3d633032019-12-10 16:37:05 +05301435func (f *OpenOltFlowMgr) deletePendingFlows(Intf uint32, onuID int32, uniID int32) {
1436 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1437 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); ok {
1438 if val.(int) > 0 {
1439 pnFlDels := val.(int) - 1
1440 if pnFlDels > 0 {
1441 log.Debugw("flow delete succeeded, more pending",
1442 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID, "currPendingFlowCnt": pnFlDels})
1443 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1444 } else {
1445 log.Debugw("all pending flow deletes handled, removing entry from map",
1446 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1447 f.pendingFlowDelete.Delete(pnFlDelKey)
1448 }
1449 }
1450 } else {
1451 log.Debugw("no pending delete flows found",
1452 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1453
1454 }
1455
1456}
1457
Girish Gowdrac3037402020-01-22 20:29:53 +05301458// Once the gemport is released for a given onu, it also has to be cleared from local cache
1459// which was used for deriving the gemport->logicalPortNo during packet-in.
1460// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1461// is conveyed to ONOS during packet-in OF message.
1462func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(intfID uint32, onuID uint32, gemPortID uint32) {
1463 f.lockCache.Lock()
1464 defer f.lockCache.Unlock()
1465 onugem := f.onuGemInfo[intfID]
serkant.uluderya96af4932020-02-20 16:58:48 -08001466 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301467 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001468 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301469 // If the gemport is found, delete it from local cache.
1470 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001471 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1472 onugem[i] = onu
Girish Gowdrac3037402020-01-22 20:29:53 +05301473 log.Debugw("removed gemport from local cache",
serkant.uluderya96af4932020-02-20 16:58:48 -08001474 log.Fields{"intfID": intfID, "onuID": onuID, "deletedGemPortID": gemPortID, "gemPorts": onu.GemPorts})
Girish Gowdrac3037402020-01-22 20:29:53 +05301475 break
1476 }
1477 }
1478 break
1479 }
1480 }
1481}
1482
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301483//clearResources clears pon resources in kv store and the device
npujarec5762e2020-01-01 14:08:48 +05301484func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301485 gemPortID int32, flowID uint32, flowDirection string,
1486 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001487
Chaitrashree G S90a17952019-11-14 21:51:21 -05001488 tpID, err := getTpIDFromFlow(flow)
1489 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001490 return olterrors.NewErrNotFound("tpid", log.Fields{"flow": flow, "pon": Intf, "onuID": onuID, "uniID": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001491 }
Gamze Abakafee36392019-10-03 11:17:24 +00001492
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001493 if len(updatedFlows) >= 0 {
1494 // There are still flows referencing the same flow_id.
1495 // So the flow should not be freed yet.
1496 // For ex: Case of HSIA where same flow is shared
1497 // between DS and US.
Girish Kumarf26e4882020-03-05 06:49:10 +00001498 if err := f.updateFlowInfoToKVStore(ctx, int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows); err != nil {
1499 olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": updatedFlows}, err).Log()
1500 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001501 if len(updatedFlows) == 0 {
Girish Gowdra3d633032019-12-10 16:37:05 +05301502 // Do this for subscriber flows only (not trap from NNI flows)
1503 if onuID != -1 && uniID != -1 {
1504 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1505 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
1506 log.Debugw("creating entry for pending flow delete",
1507 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1508 f.pendingFlowDelete.Store(pnFlDelKey, 1)
1509 } else {
1510 pnFlDels := val.(int) + 1
1511 log.Debugw("updating flow delete entry",
1512 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID, "currPendingFlowCnt": pnFlDels})
1513 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1514 }
1515
1516 defer f.deletePendingFlows(Intf, onuID, uniID)
1517 }
1518
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301519 log.Debugw("Releasing flow Id to resource manager", log.Fields{"Intf": Intf, "onuId": onuID, "uniId": uniID, "flowId": flowID})
npujarec5762e2020-01-01 14:08:48 +05301520 f.resourceMgr.FreeFlowID(ctx, Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001521
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301522 uni := getUniPortPath(Intf, onuID, uniID)
1523 tpPath := f.getTPpath(Intf, uni, tpID)
Gamze Abakafee36392019-10-03 11:17:24 +00001524 log.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
npujarec5762e2020-01-01 14:08:48 +05301525 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
Girish Kumarf26e4882020-03-05 06:49:10 +00001526 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1527 return olterrors.NewErrNotFound("tech-profile-in-kv-store", log.Fields{"tpID": tpID, "path": tpPath}, err)
Gamze Abakafee36392019-10-03 11:17:24 +00001528 }
1529
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301530 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00001531 if f.isGemPortUsedByAnotherFlow(gemPK) {
1532 flowIDs := f.flowsUsedByGemPort[gemPK]
1533 for i, flowIDinMap := range flowIDs {
1534 if flowIDinMap == flowID {
1535 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301536 // everytime flowsUsedByGemPort cache is updated the same should be updated
1537 // in kv store by calling UpdateFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001538 f.flowsUsedByGemPort[gemPK] = flowIDs
npujarec5762e2020-01-01 14:08:48 +05301539 f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs)
Gamze Abakafee36392019-10-03 11:17:24 +00001540 break
1541 }
1542 }
1543 log.Debugw("Gem port id is still used by other flows", log.Fields{"gemPortID": gemPortID, "usedByFlows": flowIDs})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301544 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00001545 }
Gamze Abakafee36392019-10-03 11:17:24 +00001546 log.Debugf("Gem port id %d is not used by another flow - releasing the gem port", gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301547 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001548 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1549 // 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 +05301550 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
Girish Gowdrac3037402020-01-22 20:29:53 +05301551 f.deleteGemPortFromLocalCache(Intf, uint32(onuID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001552 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301553 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1554 // by calling DeleteFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001555 delete(f.flowsUsedByGemPort, gemPK)
npujarec5762e2020-01-01 14:08:48 +05301556 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
1557 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001558 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05301559 // Delete the gem port on the ONU.
1560 if err := f.sendDeleteGemPortToChild(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
1561 log.Errorw("error processing delete gem-port towards onu",
1562 log.Fields{"err": err, "pon": Intf, "onuID": onuID, "uniID": uniID, "gemPortId": gemPortID})
1563 }
Gamze Abakafee36392019-10-03 11:17:24 +00001564
npujarec5762e2020-01-01 14:08:48 +05301565 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001566 if !ok {
npujarec5762e2020-01-01 14:08:48 +05301567 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID)
1568 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1569 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1570 f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID)
1571 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301572 // Delete the TCONT on the ONU.
1573 if err := f.sendDeleteTcontToChild(Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
1574 log.Errorw("error processing delete tcont towards onu",
1575 log.Fields{"pon": Intf, "onuID": onuID, "uniID": uniID, "allocId": techprofileInst.UsScheduler.AllocID})
1576 }
Gamze Abakafee36392019-10-03 11:17:24 +00001577 }
1578 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001579 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301580 return nil
1581}
1582
David K. Bainbridge794735f2020-02-11 21:01:37 -08001583// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05301584func (f *OpenOltFlowMgr) clearFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) {
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301585
1586 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowDirection": flowDirection, "flow": *flow})
Esin Karamanccb714b2019-11-29 15:02:06 +00001587
1588 if flowDirection == Multicast {
npujarec5762e2020-01-01 14:08:48 +05301589 f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00001590 return
1591 }
1592
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301593 var updatedFlows []rsrcMgr.FlowInfo
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301594 classifierInfo := make(map[string]interface{})
1595
1596 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
1597 if err != nil {
1598 log.Error(err)
1599 return
1600 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301601
David K. Bainbridge794735f2020-02-11 21:01:37 -08001602 onuID := int32(onu)
1603 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301604
1605 for _, field := range flows.GetOfbFields(flow) {
1606 if field.Type == flows.IP_PROTO {
1607 classifierInfo[IPProto] = field.GetIpProto()
1608 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
1609 }
1610 }
1611 log.Debugw("Extracted access info from flow to be deleted",
1612 log.Fields{"ponIntf": Intf, "onuID": onuID, "uniID": uniID})
1613
1614 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1615 onuID = -1
1616 uniID = -1
1617 log.Debug("Trap on nni flow set oni, uni to -1")
David K. Bainbridge794735f2020-02-11 21:01:37 -08001618 Intf, err = IntfIDFromNniPortNum(inPort)
1619 if err != nil {
1620 log.Errorw("invalid-in-port-number",
1621 log.Fields{
1622 "port-number": inPort,
1623 "error": err})
1624 return
1625 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301626 }
npujarec5762e2020-01-01 14:08:48 +05301627 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, Intf, onuID, uniID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001628 for _, flowID := range flowIds {
npujarec5762e2020-01-01 14:08:48 +05301629 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flowID)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301630 if flowInfo == nil {
1631 log.Debugw("No FlowInfo found found in KV store",
1632 log.Fields{"Intf": Intf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1633 return
1634 }
1635 updatedFlows = nil
1636 for _, flow := range *flowInfo {
1637 updatedFlows = append(updatedFlows, flow)
1638 }
1639
1640 for i, storedFlow := range updatedFlows {
1641 if flow.Id == storedFlow.LogicalFlowID {
1642 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
1643 log.Debugw("Flow to be deleted", log.Fields{"flow": storedFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001644 // DKB
1645 if err = f.removeFlowFromDevice(&removeFlowMessage); err != nil {
1646 log.Errorw("failed-to-remove-flow", log.Fields{"error": err})
1647 return
1648 }
1649 log.Debug("Flow removed from device successfully")
1650 //Remove the Flow from FlowInfo
1651 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1652 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
1653 flowID, flowDirection, portNum, updatedFlows); err != nil {
1654 log.Error("Failed to clear resources for flow", log.Fields{"flow": storedFlow})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301655 return
1656 }
1657 }
1658 }
1659 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001660}
1661
Esin Karamanccb714b2019-11-29 15:02:06 +00001662//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
1663// clears resources reserved for this multicast flow
npujarec5762e2020-01-01 14:08:48 +05301664func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) {
Esin Karamanccb714b2019-11-29 15:02:06 +00001665 classifierInfo := make(map[string]interface{})
1666 formulateClassifierInfoFromFlow(classifierInfo, flow)
npujarec5762e2020-01-01 14:08:48 +05301667 inPort, err := f.getInPortOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00001668
1669 if err != nil {
1670 log.Warnw("No inPort found. Cannot release resources of the multicast flow.", log.Fields{"flowId:": flow.Id})
1671 return
1672 }
1673
David K. Bainbridge794735f2020-02-11 21:01:37 -08001674 networkInterfaceID, err := IntfIDFromNniPortNum(inPort)
1675 if err != nil {
1676 // DKB
1677 log.Errorw("invalid-in-port-number",
1678 log.Fields{
1679 "port-number": inPort,
1680 "error": err})
1681 return
1682 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001683 var onuID = int32(NoneOnuID)
1684 var uniID = int32(NoneUniID)
1685 var flowID uint32
1686 var updatedFlows []rsrcMgr.FlowInfo
1687
npujarec5762e2020-01-01 14:08:48 +05301688 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, networkInterfaceID, onuID, uniID)
Esin Karamanccb714b2019-11-29 15:02:06 +00001689
1690 for _, flowID = range flowIds {
npujarec5762e2020-01-01 14:08:48 +05301691 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00001692 if flowInfo == nil {
1693 log.Debugw("No multicast FlowInfo found in the KV store",
1694 log.Fields{"Intf": networkInterfaceID, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1695 continue
1696 }
1697 updatedFlows = nil
1698 for _, flow := range *flowInfo {
1699 updatedFlows = append(updatedFlows, flow)
1700 }
1701 for i, storedFlow := range updatedFlows {
1702 if flow.Id == storedFlow.LogicalFlowID {
1703 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
1704 log.Debugw("Multicast flow to be deleted", log.Fields{"flow": storedFlow})
1705 //remove from device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001706 if err := f.removeFlowFromDevice(&removeFlowMessage); err != nil {
1707 // DKB
1708 log.Errorw("failed-to-remove-multicast-flow",
1709 log.Fields{
1710 "flow-id": flow.Id,
1711 "error": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00001712 return
1713 }
1714 log.Debugw("Multicast flow removed from device successfully", log.Fields{"flowId": flow.Id})
1715 //Remove the Flow from FlowInfo
1716 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
npujarec5762e2020-01-01 14:08:48 +05301717 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID), NoneOnuID, NoneUniID, flowID, &updatedFlows); err != nil {
Esin Karamanccb714b2019-11-29 15:02:06 +00001718 log.Error("Failed to delete multicast flow from the KV store", log.Fields{"flow": storedFlow, "err": err})
1719 return
1720 }
1721 //release flow id
1722 log.Debugw("Releasing multicast flow id", log.Fields{"flowId": flowID, "interfaceID": networkInterfaceID})
npujarec5762e2020-01-01 14:08:48 +05301723 f.resourceMgr.FreeFlowID(ctx, uint32(networkInterfaceID), NoneOnuID, NoneUniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00001724 }
1725 }
1726 }
1727}
1728
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001729//RemoveFlow removes the flow from the device
npujarec5762e2020-01-01 14:08:48 +05301730func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001731 log.Debugw("Removing Flow", log.Fields{"flow": flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301732 var direction string
1733 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001734
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301735 for _, action := range flows.GetActions(flow) {
1736 if action.Type == flows.OUTPUT {
1737 if out := action.GetOutput(); out != nil {
1738 actionInfo[Output] = out.GetPort()
1739 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
1740 } else {
1741 log.Error("Invalid output port in action")
1742 return
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001743 }
1744 }
1745 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001746
1747 if flows.HasGroup(flow) {
1748 direction = Multicast
1749 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301750 direction = Upstream
1751 } else {
1752 direction = Downstream
1753 }
npujarec5762e2020-01-01 14:08:48 +05301754 f.clearFlowFromResourceManager(ctx, flow, direction) //TODO: Take care of the limitations
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301755
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001756 return
1757}
1758
Girish Gowdra3d633032019-12-10 16:37:05 +05301759func (f *OpenOltFlowMgr) waitForFlowDeletesToCompleteForOnu(ctx context.Context, intfID uint32, onuID uint32,
1760 uniID uint32, ch chan bool) {
1761 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
1762 for {
1763 select {
1764 case <-time.After(20 * time.Millisecond):
1765 if flowDelRefCnt, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok || flowDelRefCnt == 0 {
1766 log.Debug("pending flow deletes completed")
1767 ch <- true
1768 return
1769 }
1770 case <-ctx.Done():
1771 log.Error("flow delete wait handler routine canceled")
1772 return
1773 }
1774 }
1775}
1776
Esin Karamanae41e2b2019-12-17 18:13:13 +00001777//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
1778func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
1779 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
1780 if ethType, ok := classifierInfo[EthType]; ok {
1781 if ethType.(uint32) == IPv4EthType {
1782 if ipProto, ok := classifierInfo[IPProto]; ok {
1783 if ipProto.(uint32) == IgmpProto {
1784 return true
1785 }
1786 }
1787 }
1788 }
1789 }
1790 return false
1791}
1792
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001793// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05301794// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01001795func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001796 classifierInfo := make(map[string]interface{})
1797 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001798 var UsMeterID uint32
1799 var DsMeterID uint32
1800
1801 log.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001802 formulateClassifierInfoFromFlow(classifierInfo, flow)
1803
1804 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
1805 if err != nil {
1806 // Error logging is already done in the called function
1807 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001808 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301809 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001810
Esin Karamanccb714b2019-11-29 15:02:06 +00001811 if flows.HasGroup(flow) {
1812 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01001813 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00001814 }
1815
manikkaraj k17652a72019-05-06 09:06:36 -04001816 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00001817 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
1818 if err != nil {
1819 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01001820 return err
manikkaraj k17652a72019-05-06 09:06:36 -04001821 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001822
David K. Bainbridge82efc492019-09-04 09:57:11 -07001823 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[Output]})
1824 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00001825
Humera Kouser94d7a842019-08-25 19:04:32 -04001826 if ethType, ok := classifierInfo[EthType]; ok {
1827 if ethType.(uint32) == LldpEthType {
1828 log.Info("Adding LLDP flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01001829 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04001830 }
1831 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001832 if ipProto, ok := classifierInfo[IPProto]; ok {
1833 if ipProto.(uint32) == IPProtoDhcp {
1834 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05301835 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001836 log.Debug("trap-dhcp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01001837 return f.addDHCPTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001838 }
1839 }
1840 }
1841 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001842 if isIgmpTrapDownstreamFlow(classifierInfo) {
1843 log.Debug("trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01001844 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001845 }
A R Karthick1f85b802019-10-11 05:06:05 +00001846
1847 f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
npujarec5762e2020-01-01 14:08:48 +05301848 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00001849
Chaitrashree G S90a17952019-11-14 21:51:21 -05001850 TpID, err := getTpIDFromFlow(flow)
1851 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001852 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 -05001853 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001854 log.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001855 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07001856 UsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001857 log.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
1858 } else {
Scott Baker355d1742019-10-24 10:57:52 -07001859 DsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001860 log.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
1861
1862 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301863
1864 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
1865 if _, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
1866 log.Debugw("no pending flows found, going ahead with flow install", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
npujarec5762e2020-01-01 14:08:48 +05301867 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05301868 } else {
Girish Gowdra3d633032019-12-10 16:37:05 +05301869 pendingFlowDelComplete := make(chan bool)
1870 go f.waitForFlowDeletesToCompleteForOnu(ctx, intfID, onuID, uniID, pendingFlowDelComplete)
1871 select {
1872 case <-pendingFlowDelComplete:
1873 log.Debugw("all pending flow deletes completed", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
npujarec5762e2020-01-01 14:08:48 +05301874 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05301875
1876 case <-time.After(10 * time.Second):
Girish Kumarf26e4882020-03-05 06:49:10 +00001877 return olterrors.NewErrTimeout("pending-flow-deletes", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID}, nil)
Girish Gowdra3d633032019-12-10 16:37:05 +05301878 }
1879 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001880 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001881}
1882
Esin Karamanccb714b2019-11-29 15:02:06 +00001883// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08001884func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00001885 classifierInfo[PacketTagType] = DoubleTag
1886 log.Debugw("add-multicast-flow", log.Fields{"classifierInfo": classifierInfo, "actionInfo": actionInfo})
1887
npujarec5762e2020-01-01 14:08:48 +05301888 inPort, err := f.getInPortOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00001889 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001890 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00001891 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00001892 //this variable acts like a switch. When it is set, multicast flows are classified by eth_dst.
1893 //otherwise, classification is based on ipv4_dst by default.
1894 //the variable can be configurable in the future; it can be read from a configuration path in the kv store.
1895 mcastFlowClassificationByEthDst := false
1896
1897 if mcastFlowClassificationByEthDst {
1898 //replace ipDst with ethDst
1899 if ipv4Dst, ok := classifierInfo[Ipv4Dst]; ok &&
1900 flows.IsMulticastIp(ipv4Dst.(uint32)) {
1901 // replace ipv4_dst classifier with eth_dst
1902 multicastMac := flows.ConvertToMulticastMacBytes(ipv4Dst.(uint32))
1903 delete(classifierInfo, Ipv4Dst)
1904 classifierInfo[EthDst] = multicastMac
1905 log.Debugw("multicast-ip-to-mac-conversion-success", log.Fields{"ip:": ipv4Dst.(uint32), "mac:": multicastMac})
1906 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001907 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00001908 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00001909
David K. Bainbridge794735f2020-02-11 21:01:37 -08001910 onuID := NoneOnuID
1911 uniID := NoneUniID
1912 gemPortID := NoneGemPortID
Esin Karamanccb714b2019-11-29 15:02:06 +00001913
David K. Bainbridge794735f2020-02-11 21:01:37 -08001914 networkInterfaceID, err := IntfIDFromNniPortNum(inPort)
1915 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001916 return olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001917 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001918
David K. Bainbridge794735f2020-02-11 21:01:37 -08001919 flowStoreCookie := getFlowStoreCookie(classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05301920 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001921 log.Debugw("multicast-flow-exists-not-re-adding", log.Fields{"classifierInfo": classifierInfo})
1922 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00001923 }
npujarec5762e2020-01-01 14:08:48 +05301924 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanccb714b2019-11-29 15:02:06 +00001925 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301926 return olterrors.NewErrNotFound("multicast-flow-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001927 "interface-id": networkInterfaceID,
1928 "onu-id": onuID,
1929 "uni-id": uniID,
1930 "gem-port-id": gemPortID,
1931 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00001932 err)
Esin Karamanccb714b2019-11-29 15:02:06 +00001933 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001934 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1935 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001936 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00001937 }
1938 groupID := actionInfo[GroupID].(uint32)
1939 multicastFlow := openoltpb2.Flow{
1940 FlowId: flowID,
1941 FlowType: Multicast,
1942 NetworkIntfId: int32(networkInterfaceID),
1943