blob: c16d44c709791aad3f64586493bb373273730ae6 [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
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070017//Package adaptercore provides the utility for olt devices, flows and statistics
manikkaraj kbf256be2019-03-25 00:13:48 +053018package adaptercore
19
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"
25 "errors"
26 "fmt"
Manikkaraj kb1d51442019-07-23 10:41:02 -040027 "math/big"
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
Scott Baker51290152019-10-24 14:23:20 -070031 "github.com/opencord/voltha-lib-go/v2/pkg/flows"
32 "github.com/opencord/voltha-lib-go/v2/pkg/log"
33 tp "github.com/opencord/voltha-lib-go/v2/pkg/techprofile"
Manikkaraj k884c1242019-04-11 16:26:42 +053034 rsrcMgr "github.com/opencord/voltha-openolt-adapter/adaptercore/resourcemanager"
Scott Bakerc6e54cb2019-11-04 09:31:25 -080035 "github.com/opencord/voltha-protos/v2/go/common"
36 ic "github.com/opencord/voltha-protos/v2/go/inter_container"
37 ofp "github.com/opencord/voltha-protos/v2/go/openflow_13"
38 openoltpb2 "github.com/opencord/voltha-protos/v2/go/openolt"
39 tp_pb "github.com/opencord/voltha-protos/v2/go/tech_profile"
40 "github.com/opencord/voltha-protos/v2/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"
Daniele Rossi22db98e2019-07-11 11:50:00 +000044 "google.golang.org/grpc/codes"
45 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053046)
47
48const (
49 // Flow categories
manikkaraj kbf256be2019-03-25 00:13:48 +053050
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070051 //HsiaFlow flow category
52 HsiaFlow = "HSIA_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053053
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070054 //EapolFlow flow category
55 EapolFlow = "EAPOL_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053056
Manikkaraj kb1d51442019-07-23 10:41:02 -040057 //DhcpFlow flow category
58 DhcpFlow = "DHCP_FLOW"
59
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070060 //IPProtoDhcp flow category
61 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053062
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070063 //IPProtoIgmp flow category
64 IPProtoIgmp = 2
65
66 //EapEthType eapethtype value
67 EapEthType = 0x888e
68 //LldpEthType lldp ethtype value
69 LldpEthType = 0x88cc
70
71 //IgmpProto proto value
72 IgmpProto = 2
manikkaraj kbf256be2019-03-25 00:13:48 +053073
74 //FIXME - see also BRDCM_DEFAULT_VLAN in broadcom_onu.py
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070075
Humera Kouser94d7a842019-08-25 19:04:32 -040076 //ReservedVlan Transparent Vlan
David K. Bainbridge82efc492019-09-04 09:57:11 -070077 ReservedVlan = 4095
Harsh Awasthiea45af72019-08-26 02:39:00 -040078
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070079 //DefaultMgmtVlan default vlan value
80 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053081
manikkaraj kbf256be2019-03-25 00:13:48 +053082 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070083
David K. Bainbridge82efc492019-09-04 09:57:11 -070084 //Upstream constant
85 Upstream = "upstream"
86 //Downstream constant
87 Downstream = "downstream"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070088 //PacketTagType constant
89 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070090 //Untagged constant
91 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070092 //SingleTag constant
93 SingleTag = "single_tag"
94 //DoubleTag constant
95 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053096
97 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070098
99 //EthType constant
100 EthType = "eth_type"
101 //TPID constant
102 TPID = "tpid"
103 //IPProto constant
104 IPProto = "ip_proto"
105 //InPort constant
106 InPort = "in_port"
107 //VlanVid constant
108 VlanVid = "vlan_vid"
109 //VlanPcp constant
110 VlanPcp = "vlan_pcp"
111
112 //UDPDst constant
113 UDPDst = "udp_dst"
114 //UDPSrc constant
115 UDPSrc = "udp_src"
116 //Ipv4Dst constant
117 Ipv4Dst = "ipv4_dst"
118 //Ipv4Src constant
119 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700120 //Metadata constant
121 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700122 //TunnelID constant
123 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700124 //Output constant
125 Output = "output"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700126 // Actions
127
128 //PopVlan constant
129 PopVlan = "pop_vlan"
130 //PushVlan constant
131 PushVlan = "push_vlan"
132 //TrapToHost constant
133 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400134 //MaxMeterBand constant
135 MaxMeterBand = 2
136 //VlanPCPMask contant
137 VlanPCPMask = 0xFF
138 //VlanvIDMask constant
139 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000140 //IntfID constant
141 IntfID = "intfId"
142 //OnuID constant
143 OnuID = "onuId"
144 //UniID constant
145 UniID = "uniId"
146 //PortNo constant
147 PortNo = "portNo"
148 //AllocID constant
149 AllocID = "allocId"
manikkaraj kbf256be2019-03-25 00:13:48 +0530150)
151
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400152type gemPortKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700153 intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400154 gemPort uint32
155}
156
Girish Gowdra3d633032019-12-10 16:37:05 +0530157type pendingFlowDeleteKey struct {
158 intfID uint32
159 onuID uint32
160 uniID uint32
161}
162
163type tpLockKey struct {
164 intfID uint32
165 onuID uint32
166 uniID uint32
167}
168
Gamze Abakafee36392019-10-03 11:17:24 +0000169type schedQueue struct {
170 direction tp_pb.Direction
171 intfID uint32
172 onuID uint32
173 uniID uint32
174 tpID uint32
175 uniPort uint32
176 tpInst *tp.TechProfile
177 meterID uint32
178 flowMetadata *voltha.FlowMetadata
179}
180
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700181//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530182type OpenOltFlowMgr struct {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000183 techprofile map[uint32]tp.TechProfileIf
Gamze Abakafee36392019-10-03 11:17:24 +0000184 deviceHandler *DeviceHandler
185 resourceMgr *rsrcMgr.OpenOltResourceMgr
Gamze Abakafee36392019-10-03 11:17:24 +0000186 onuIdsLock sync.RWMutex
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530187 flowsUsedByGemPort map[gemPortKey][]uint32 //gem port id to flow ids
188 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
189 onuGemInfo map[uint32][]rsrcMgr.OnuGemInfo //onu, gem and uni info local cache
190 lockCache sync.RWMutex
Girish Gowdra3d633032019-12-10 16:37:05 +0530191 pendingFlowDelete sync.Map
192 // The mapmutex.Mutex can be fine tuned to use mapmutex.NewCustomizedMapMutex
193 perUserFlowHandleLock *mapmutex.Mutex
manikkaraj kbf256be2019-03-25 00:13:48 +0530194}
195
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700196//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530197func NewFlowManager(dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
manikkaraj kbf256be2019-03-25 00:13:48 +0530198 log.Info("Initializing flow manager")
199 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530200 var err error
201 var idx uint32
202
manikkaraj kbf256be2019-03-25 00:13:48 +0530203 flowMgr.deviceHandler = dh
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530204 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000205 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530206 if err = flowMgr.populateTechProfilePerPonPort(); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530207 log.Error("Error while populating tech profile mgr\n")
208 return nil
209 }
William Kurkian740a09c2019-10-23 17:07:38 -0400210 flowMgr.onuIdsLock = sync.RWMutex{}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530211 flowMgr.flowsUsedByGemPort = make(map[gemPortKey][]uint32)
212 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
213 flowMgr.onuGemInfo = make(map[uint32][]rsrcMgr.OnuGemInfo)
214 ponPorts := rMgr.DevInfo.GetPonPorts()
215 //Load the onugem info cache from kv store on flowmanager start
216 for idx = 0; idx < ponPorts; idx++ {
217 if flowMgr.onuGemInfo[idx], err = rMgr.GetOnuGemInfo(idx); err != nil {
218 log.Error("Failed to load onu gem info cache")
219 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530220 //Load flowID list per gem map per interface from the kvstore.
221 flowMgr.loadFlowIDlistForGem(idx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530222 }
223 flowMgr.lockCache = sync.RWMutex{}
Girish Gowdra3d633032019-12-10 16:37:05 +0530224 flowMgr.pendingFlowDelete = sync.Map{}
225 flowMgr.perUserFlowHandleLock = mapmutex.NewMapMutex()
manikkaraj kbf256be2019-03-25 00:13:48 +0530226 log.Info("Initialization of flow manager success!!")
227 return &flowMgr
228}
229
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700230func (f *OpenOltFlowMgr) generateStoredFlowID(flowID uint32, direction string) (uint64, error) {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700231 if direction == Upstream {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400232 log.Debug("upstream flow, shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700233 return 0x1<<15 | uint64(flowID), nil
David K. Bainbridge82efc492019-09-04 09:57:11 -0700234 } else if direction == Downstream {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400235 log.Debug("downstream flow, not shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700236 return uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400237 } else {
238 log.Debug("Unrecognized direction")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700239 return 0, fmt.Errorf("unrecognized direction %s", direction)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400240 }
241}
242
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700243func (f *OpenOltFlowMgr) registerFlow(flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400244 log.Debug("Registering Flow for Device ", log.Fields{"flow": flowFromCore},
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700245 log.Fields{"device": f.deviceHandler.deviceID})
Gamze Abakafee36392019-10-03 11:17:24 +0000246 gemPK := gemPortKey{uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId)}
247 flowIDList, ok := f.flowsUsedByGemPort[gemPK]
248 if !ok {
249 flowIDList = []uint32{deviceFlow.FlowId}
250 }
251 flowIDList = appendUnique(flowIDList, deviceFlow.FlowId)
252 f.flowsUsedByGemPort[gemPK] = flowIDList
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530253 // update the flowids for a gem to the KVstore
254 f.resourceMgr.UpdateFlowIDsForGem(uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400255}
256
salmansiddiqui7ac62132019-08-22 03:58:50 +0000257func (f *OpenOltFlowMgr) divideAndAddFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32,
258 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
259 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) {
Gamze Abakafee36392019-10-03 11:17:24 +0000260 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530261 var gemPorts []uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400262 var TpInst *tp.TechProfile
manikkaraj kbf256be2019-03-25 00:13:48 +0530263
Manikkaraj kb1d51442019-07-23 10:41:02 -0400264 log.Infow("Dividing flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "portNo": portNo,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000265 "classifier": classifierInfo, "action": actionInfo, "UsMeterID": UsMeterID, "DsMeterID": DsMeterID, "TpID": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400266 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
267 // is because the flow is an NNI flow and there would be no onu resources associated with it
268 // TODO: properly deal with NNI flows
Manikkaraj kb1d51442019-07-23 10:41:02 -0400269 if onuID <= 0 {
Matt Jeanneret77199612019-07-26 18:08:35 -0400270 log.Errorw("No onu id for flow", log.Fields{"portNo": portNo, "classifer": classifierInfo, "action": actionInfo})
manikkaraj kbf256be2019-03-25 00:13:48 +0530271 return
272 }
273
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530274 uni := getUniPortPath(intfID, int32(onuID), int32(uniID))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400275 log.Debugw("Uni port name", log.Fields{"uni": uni})
Girish Gowdra3d633032019-12-10 16:37:05 +0530276
277 tpLockMapKey := tpLockKey{intfID, onuID, uniID}
278 if f.perUserFlowHandleLock.TryLock(tpLockMapKey) {
279 allocID, gemPorts, TpInst = f.createTcontGemports(intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
280 if allocID == 0 || gemPorts == nil || TpInst == nil {
281 log.Error("alloc-id-gem-ports-tp-unavailable")
282 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
283 return
284 }
285 args := make(map[string]uint32)
286 args[IntfID] = intfID
287 args[OnuID] = onuID
288 args[UniID] = uniID
289 args[PortNo] = portNo
290 args[AllocID] = allocID
291
292 /* Flows can be added specific to gemport if p-bits are received.
293 * If no pbit mentioned then adding flows for all gemports
294 */
295 f.checkAndAddFlow(args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
296 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
297 } else {
298 log.Errorw("failed to acquire per user flow handle lock",
299 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400300 return
301 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530302}
303
salmansiddiqui7ac62132019-08-22 03:58:50 +0000304// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
Gamze Abakafee36392019-10-03 11:17:24 +0000305func (f *OpenOltFlowMgr) CreateSchedulerQueues(sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400306
Gamze Abakafee36392019-10-03 11:17:24 +0000307 log.Debugw("CreateSchedulerQueues", log.Fields{"Dir": sq.direction, "IntfID": sq.intfID,
308 "OnuID": sq.onuID, "UniID": sq.uniID, "TpID": sq.tpID, "MeterID": sq.meterID,
309 "TpInst": sq.tpInst, "flowMetadata": sq.flowMetadata})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400310
Gamze Abakafee36392019-10-03 11:17:24 +0000311 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000312 if err != nil {
313 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400314 }
315
316 /* Lets make a simple assumption that if the meter-id is present on the KV store,
317 * then the scheduler and queues configuration is applied on the OLT device
318 * in the given direction.
319 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000320
Manikkaraj kb1d51442019-07-23 10:41:02 -0400321 var SchedCfg *tp_pb.SchedulerConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000322 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400323 if err != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000324 log.Error("Failed to get meter for intf %d, onuid %d, uniid %d", sq.intfID, sq.onuID, sq.uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400325 return err
326 }
327 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000328 if KvStoreMeter.MeterId == sq.meterID {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400329 log.Debug("Scheduler already created for upstream")
330 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400331 }
Gamze Abakafee36392019-10-03 11:17:24 +0000332 log.Errorw("Dynamic meter update not supported", log.Fields{"KvStoreMeterId": KvStoreMeter.MeterId, "MeterID-in-flow": sq.meterID})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000333 return errors.New("invalid-meter-id-in-flow")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400334 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000335
Gamze Abakafee36392019-10-03 11:17:24 +0000336 log.Debugw("Meter-does-not-exist-Creating-new", log.Fields{"MeterID": sq.meterID, "Direction": Direction})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000337
Gamze Abakafee36392019-10-03 11:17:24 +0000338 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000339 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Gamze Abakafee36392019-10-03 11:17:24 +0000340 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000341 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400342 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000343
344 if err != nil {
345 log.Errorw("Unable to get Scheduler config", log.Fields{"IntfID": sq.intfID, "Direction": sq.direction, "Error": err})
346 return err
347 }
348
Manikkaraj kb1d51442019-07-23 10:41:02 -0400349 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000350 if sq.flowMetadata != nil {
351 for _, meter := range sq.flowMetadata.Meters {
352 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400353 meterConfig = meter
354 log.Debugw("Found-meter-config-from-flowmetadata", log.Fields{"meterConfig": meterConfig})
355 break
356 }
357 }
358 } else {
359 log.Error("Flow-metadata-is-not-present-in-flow")
360 }
361 if meterConfig == nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000362 log.Errorw("Could-not-get-meterbands-from-flowMetadata", log.Fields{"flowMetadata": sq.flowMetadata,
363 "MeterID": sq.meterID})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000364 return errors.New("failed-to-get-meter-from-flowMetadata")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400365 } else if len(meterConfig.Bands) < MaxMeterBand {
Gamze Abakafee36392019-10-03 11:17:24 +0000366 log.Errorw("Invalid-number-of-bands-in-meter", log.Fields{"Bands": meterConfig.Bands, "MeterID": sq.meterID})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000367 return errors.New("invalid-number-of-bands-in-meter")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400368 }
369 cir := meterConfig.Bands[0].Rate
370 cbs := meterConfig.Bands[0].BurstSize
371 eir := meterConfig.Bands[1].Rate
372 ebs := meterConfig.Bands[1].BurstSize
373 pir := cir + eir
374 pbs := cbs + ebs
375 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
376
Gamze Abakafee36392019-10-03 11:17:24 +0000377 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Manikkaraj kb1d51442019-07-23 10:41:02 -0400378
Girish Kumar8f73fe02019-12-09 13:19:37 +0000379 if err := f.pushSchedulerQueuesToDevice(sq, TrafficShaping, TrafficSched); err != nil {
380 log.Errorw("Failed to push traffic scheduler and queues to device", log.Fields{"intfID": sq.intfID, "direction": sq.direction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400381 return err
382 }
383
salmansiddiqui7ac62132019-08-22 03:58:50 +0000384 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400385 * store the meter id on the KV store, for further reference.
386 */
Gamze Abakafee36392019-10-03 11:17:24 +0000387 if err := f.resourceMgr.UpdateMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterConfig); err != nil {
388 log.Error("Failed to update meter id for onu %d, meterid %d", sq.onuID, sq.meterID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400389 return err
390 }
391 log.Debugw("updated-meter-info into KV store successfully", log.Fields{"Direction": Direction,
392 "Meter": meterConfig})
393 return nil
394}
395
Girish Kumar8f73fe02019-12-09 13:19:37 +0000396func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(sq schedQueue, TrafficShaping *tp_pb.TrafficShapingInfo, TrafficSched []*tp_pb.TrafficScheduler) error {
397
398 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
399
400 if err != nil {
401 log.Errorw("Unable to construct traffic queue configuration", log.Fields{"intfID": sq.intfID, "direction": sq.direction})
402 return err
403 }
404
405 log.Debugw("Sending Traffic scheduler create to device", log.Fields{"Direction": sq.direction, "TrafficScheds": TrafficSched})
406 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
407 IntfId: sq.intfID, OnuId: sq.onuID,
408 UniId: sq.uniID, PortNo: sq.uniPort,
409 TrafficScheds: TrafficSched}); err != nil {
410 log.Errorw("Failed to create traffic schedulers", log.Fields{"error": err})
411 return err
412 }
413
414 // On receiving the CreateTrafficQueues request, the driver should create corresponding
415 // downstream queues.
416 log.Debugw("Sending Traffic Queues create to device", log.Fields{"Direction": sq.direction, "TrafficQueues": trafficQueues})
417 if _, err := f.deviceHandler.Client.CreateTrafficQueues(context.Background(),
418 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
419 UniId: sq.uniID, PortNo: sq.uniPort,
420 TrafficQueues: trafficQueues}); err != nil {
421 log.Errorw("Failed to create traffic queues in device", log.Fields{"error": err})
422 return err
423 }
424
425 return nil
426}
427
salmansiddiqui7ac62132019-08-22 03:58:50 +0000428// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
Gamze Abakafee36392019-10-03 11:17:24 +0000429func (f *OpenOltFlowMgr) RemoveSchedulerQueues(sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400430
431 var Direction string
432 var SchedCfg *tp_pb.SchedulerConfig
433 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000434 log.Debugw("Removing schedulers and Queues in OLT", log.Fields{"Direction": sq.direction, "IntfID": sq.intfID,
435 "OnuID": sq.onuID, "UniID": sq.uniID, "UniPort": sq.uniPort})
436 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000437 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400438 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000439 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000440 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400441 Direction = "downstream"
442 }
443
Girish Kumar8f73fe02019-12-09 13:19:37 +0000444 if err != nil {
445 log.Errorw("Unable to get Scheduler config", log.Fields{"IntID": sq.intfID, "Direction": sq.direction, "Error": err})
446 return err
447 }
448
Gamze Abakafee36392019-10-03 11:17:24 +0000449 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400450 if err != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000451 log.Errorf("Failed to get Meter for Onu %d", sq.onuID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400452 return err
453 }
454 if KVStoreMeter == nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000455 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 -0400456 return nil
457 }
458 cir := KVStoreMeter.Bands[0].Rate
459 cbs := KVStoreMeter.Bands[0].BurstSize
460 eir := KVStoreMeter.Bands[1].Rate
461 ebs := KVStoreMeter.Bands[1].BurstSize
462 pir := cir + eir
463 pbs := cbs + ebs
464
465 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
466
Gamze Abakafee36392019-10-03 11:17:24 +0000467 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Girish Kumar8f73fe02019-12-09 13:19:37 +0000468
469 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
470 if err != nil {
471 log.Errorw("Unable to construct traffic queue configuration", log.Fields{"intfID": sq.intfID, "direction": sq.direction})
472 return err
473 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400474
475 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(context.Background(),
Gamze Abakafee36392019-10-03 11:17:24 +0000476 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
477 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400478 TrafficQueues: TrafficQueues}); err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000479 log.Errorw("Failed to remove traffic queues", log.Fields{"error": err})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400480 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400481 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000482 log.Debug("Removed traffic queues successfully")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400483 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000484 IntfId: sq.intfID, OnuId: sq.onuID,
485 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400486 TrafficScheds: TrafficSched}); err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000487 log.Errorw("failed to remove traffic schedulers", log.Fields{"error": err})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400488 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400489 }
490
salmansiddiqui7ac62132019-08-22 03:58:50 +0000491 log.Debug("Removed traffic schedulers successfully")
492
493 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400494 * delete the meter id on the KV store.
495 */
Gamze Abakafee36392019-10-03 11:17:24 +0000496 err = f.resourceMgr.RemoveMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400497 if err != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000498 log.Errorf("Failed to remove meter for onu %d, meter id %d", sq.onuID, KVStoreMeter.MeterId)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000499 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400500 }
501 log.Debugw("Removed-meter-from-KV-store successfully", log.Fields{"MeterId": KVStoreMeter.MeterId, "dir": Direction})
502 return err
503}
504
Gamze Abakafee36392019-10-03 11:17:24 +0000505// This function allocates tconts and GEM ports for an ONU
506func (f *OpenOltFlowMgr) createTcontGemports(intfID uint32, onuID uint32, uniID uint32, uni string, uniPort uint32, TpID uint32, UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) (uint32, []uint32, *tp.TechProfile) {
507 var allocIDs []uint32
508 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530509 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530510 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000511 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000512
513 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(intfID, onuID, uniID)
514 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400515
516 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530517
518 log.Infow("creating-new-tcont-and-gem", log.Fields{"pon": intfID, "onu": onuID, "uni": uniID})
519
Manikkaraj kb1d51442019-07-23 10:41:02 -0400520 // Check tech profile instance already exists for derived port name
Girish Gowdra54934262019-11-13 14:19:55 +0530521 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000522 if techProfileInstance == nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530523 log.Infow("tp-instance-not-found--creating-new", log.Fields{"path": tpPath})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000524 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(TpID, uni, intfID)
525 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530526 // This should not happen, something wrong in KV backend transaction
Girish Kumar8f73fe02019-12-09 13:19:37 +0000527 log.Errorw("tp-instance-create-failed", log.Fields{"error": err, "tpID": TpID})
Gamze Abakafee36392019-10-03 11:17:24 +0000528 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530529 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000530 f.resourceMgr.UpdateTechProfileIDForOnu(intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530531 } else {
532 log.Debugw("Tech-profile-instance-already-exist-for-given port-name", log.Fields{"uni": uni})
Girish Gowdra3d633032019-12-10 16:37:05 +0530533 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530534 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400535 if UsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000536 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
537 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
538 if err := f.CreateSchedulerQueues(sq); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400539 log.Errorw("CreateSchedulerQueues Failed-upstream", log.Fields{"error": err, "meterID": UsMeterID})
Gamze Abakafee36392019-10-03 11:17:24 +0000540 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400541 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530542 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400543 if DsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000544 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
545 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
546 if err := f.CreateSchedulerQueues(sq); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400547 log.Errorw("CreateSchedulerQueues Failed-downstream", log.Fields{"error": err, "meterID": DsMeterID})
Gamze Abakafee36392019-10-03 11:17:24 +0000548 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400549 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530550 }
Gamze Abakafee36392019-10-03 11:17:24 +0000551
552 allocID := techProfileInstance.UsScheduler.AllocID
Gamze Abakafee36392019-10-03 11:17:24 +0000553 for _, gem := range techProfileInstance.UpstreamGemPortAttributeList {
Gamze Abakafee36392019-10-03 11:17:24 +0000554 gemPortIDs = append(gemPortIDs, gem.GemportID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400555 }
Gamze Abakafee36392019-10-03 11:17:24 +0000556
Girish Gowdra3d633032019-12-10 16:37:05 +0530557 if tpInstanceExists {
558 return allocID, gemPortIDs, techProfileInstance
559 }
560
561 allocIDs = appendUnique(allocIDs, allocID)
562 for _, gemPortID := range gemPortIDs {
563 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
564 }
565
Gamze Abakafee36392019-10-03 11:17:24 +0000566 log.Debugw("Allocated Tcont and GEM ports", log.Fields{"allocIDs": allocIDs, "gemports": allgemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530567 // Send Tconts and GEM ports to KV store
Gamze Abakafee36392019-10-03 11:17:24 +0000568 f.storeTcontsGEMPortsIntoKVStore(intfID, onuID, uniID, allocIDs, allgemPortIDs)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000569 return allocID, gemPortIDs, techProfileInstance
manikkaraj kbf256be2019-03-25 00:13:48 +0530570}
571
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700572func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530573
574 log.Debugw("Storing allocated Tconts and GEM ports into KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700575 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "allocID": allocID, "gemPortIDs": gemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530576 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700577 if err := f.resourceMgr.UpdateAllocIdsForOnu(intfID, onuID, uniID, allocID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530578 log.Error("Errow while uploading allocID to KV store")
579 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700580 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(intfID, onuID, uniID, gemPortIDs); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530581 log.Error("Errow while uploading GEMports to KV store")
582 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700583 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(gemPortIDs, intfID, onuID, uniID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530584 log.Error("Errow while uploading gemtopon map to KV store")
585 }
586 log.Debug("Stored tconts and GEM into KV store successfully")
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400587 for _, gemPort := range gemPortIDs {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700588 f.addGemPortToOnuInfoMap(intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400589 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530590}
591
592func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000593 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530594 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000595 for _, intfID := range techRange.IntfIds {
596 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400597 tpCount++
salmansiddiqui7ac62132019-08-22 03:58:50 +0000598 log.Debugw("Init tech profile done", log.Fields{"intfID": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530599 }
600 }
601 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400602 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530603 log.Errorw("Error while populating techprofile",
Manikkaraj kb1d51442019-07-23 10:41:02 -0400604 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000605 return errors.New("error while populating techprofile mgrs")
manikkaraj kbf256be2019-03-25 00:13:48 +0530606 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400607 log.Infow("Populated techprofile for ponports successfully",
608 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
manikkaraj kbf256be2019-03-25 00:13:48 +0530609 return nil
610}
611
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700612func (f *OpenOltFlowMgr) addUpstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530613 portNo uint32, uplinkClassifier map[string]interface{},
614 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700615 allocID uint32, gemportID uint32) {
616 uplinkClassifier[PacketTagType] = SingleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530617 log.Debugw("Adding upstream data flow", log.Fields{"uplinkClassifier": uplinkClassifier, "uplinkAction": uplinkAction})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700618 f.addHSIAFlow(intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700619 Upstream, logicalFlow, allocID, gemportID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530620 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530621}
622
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700623func (f *OpenOltFlowMgr) addDownstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530624 portNo uint32, downlinkClassifier map[string]interface{},
625 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700626 allocID uint32, gemportID uint32) {
627 downlinkClassifier[PacketTagType] = DoubleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530628 log.Debugw("Adding downstream data flow", log.Fields{"downlinkClassifier": downlinkClassifier,
629 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400630 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
631 if vlan, exists := downlinkClassifier[VlanVid]; exists {
632 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700633 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Manikkaraj kb1d51442019-07-23 10:41:02 -0400634 if uint32(metadata.(uint64)) == MkUniPortNum(intfID, onuID, uniID) {
635 log.Infow("Ignoring DL trap device flow from core", log.Fields{"flow": logicalFlow})
636 return
637 }
638 }
639 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530640 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400641
Manikkaraj k884c1242019-04-11 16:26:42 +0530642 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700643 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400644 // vlan_vid is a uint32. must be type asserted as such or conversion fails
645 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530646 if ok {
647 downlinkAction[VlanVid] = dlClVid & 0xfff
648 } else {
649 log.Error("dl-classifier-vid-type-conversion-failed")
650 return
651 }
652
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700653 f.addHSIAFlow(intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700654 Downstream, logicalFlow, allocID, gemportID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530655}
656
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700657func (f *OpenOltFlowMgr) addHSIAFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +0530658 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700659 allocID uint32, gemPortID uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530660 var networkIntfID uint32
Manikkaraj k884c1242019-04-11 16:26:42 +0530661 /* One of the OLT platform (Broadcom BAL) requires that symmetric
662 flows require the same flow_id to be used across UL and DL.
663 Since HSIA flow is the only symmetric flow currently, we need to
664 re-use the flow_id across both direction. The 'flow_category'
665 takes priority over flow_cookie to find any available HSIA_FLOW
666 id for the ONU.
667 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700668 log.Debugw("Adding HSIA flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "classifier": classifier,
669 "action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530670 "logicalFlow": *logicalFlow})
Gamze Abakafee36392019-10-03 11:17:24 +0000671 var vlanPbit uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400672 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000673 vlanPbit = classifier[VlanPcp].(uint32)
674 log.Debugw("Found pbit in the flow", log.Fields{"VlanPbit": vlanPbit})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400675 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700676 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Girish Gowdra3d633032019-12-10 16:37:05 +0530677 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
678 log.Debug("Flow-exists--not-re-adding")
679 return
680 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530681 flowID, err := f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530682 if err != nil {
683 log.Errorw("Flow id unavailable for HSIA flow", log.Fields{"direction": direction})
684 return
685 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700686 var classifierProto *openoltpb2.Classifier
687 var actionProto *openoltpb2.Action
Manikkaraj k884c1242019-04-11 16:26:42 +0530688 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
689 log.Error("Error in making classifier protobuf for hsia flow")
690 return
691 }
692 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
693 if actionProto = makeOpenOltActionField(action); actionProto == nil {
694 log.Errorw("Error in making action protobuf for hsia flow", log.Fields{"direction": direction})
695 return
696 }
697 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530698 networkIntfID, err = getNniIntfID(classifier, action)
699 if err != nil {
700 log.Error("Failed to get nniIntf ID")
701 return
702 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700703 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
704 OnuId: int32(onuID),
705 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000706 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530707 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700708 AllocId: int32(allocID),
709 NetworkIntfId: int32(networkIntfID),
710 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530711 Classifier: classifierProto,
712 Action: actionProto,
713 Priority: int32(logicalFlow.Priority),
714 Cookie: logicalFlow.Cookie,
715 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400716 if ok := f.addFlowToDevice(logicalFlow, &flow); ok {
Manikkaraj k884c1242019-04-11 16:26:42 +0530717 log.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530718 flowsToKVStore := f.getUpdatedFlowInfo(&flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
Manikkaraj k884c1242019-04-11 16:26:42 +0530719 if err := f.updateFlowInfoToKVStore(flow.AccessIntfId,
720 flow.OnuId,
721 flow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400722 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530723 log.Errorw("Error uploading HSIA flow into KV store", log.Fields{"flow": flow, "direction": direction, "error": err})
724 return
725 }
726 }
727}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700728func (f *OpenOltFlowMgr) addDHCPTrapFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32) {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530729
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700730 var dhcpFlow openoltpb2.Flow
731 var actionProto *openoltpb2.Action
732 var classifierProto *openoltpb2.Classifier
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530733 var flowID uint32
734 networkIntfID, err := getNniIntfID(classifier, action)
735 if err != nil {
736 log.Error("Failed to get nniIntf ID")
737 return
738 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530739
740 // Clear the action map
741 for k := range action {
742 delete(action, k)
743 }
744
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700745 action[TrapToHost] = true
746 classifier[UDPSrc] = uint32(68)
747 classifier[UDPDst] = uint32(67)
748 classifier[PacketTagType] = SingleTag
749 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530750
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700751 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Girish Gowdra3d633032019-12-10 16:37:05 +0530752 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
753 log.Debug("Flow-exists--not-re-adding")
754 return
755 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530756
Girish Gowdra3d633032019-12-10 16:37:05 +0530757 flowID, err = f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, DhcpFlow, 0 /*classifier[VLAN_PCP].(uint32)*/)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530758
759 if err != nil {
Girish Gowdra3d633032019-12-10 16:37:05 +0530760 log.Errorw("flowId unavailable for UL DHCP", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530761 return
762 }
763
764 log.Debugw("Creating UL DHCP flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID})
765
766 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
767 log.Error("Error in making classifier protobuf for ul flow")
768 return
769 }
770 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
771 if actionProto = makeOpenOltActionField(action); actionProto == nil {
772 log.Error("Error in making action protobuf for ul flow")
773 return
774 }
775
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700776 dhcpFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
777 OnuId: int32(onuID),
778 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530779 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700780 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700781 AllocId: int32(allocID),
782 NetworkIntfId: int32(networkIntfID),
783 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530784 Classifier: classifierProto,
785 Action: actionProto,
786 Priority: int32(logicalFlow.Priority),
787 Cookie: logicalFlow.Cookie,
788 PortNo: portNo}
789
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400790 if ok := f.addFlowToDevice(logicalFlow, &dhcpFlow); ok {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530791 log.Debug("DHCP UL flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530792 flowsToKVStore := f.getUpdatedFlowInfo(&dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530793 if err := f.updateFlowInfoToKVStore(dhcpFlow.AccessIntfId,
794 dhcpFlow.OnuId,
795 dhcpFlow.UniId,
796 dhcpFlow.FlowId, flowsToKVStore); err != nil {
797 log.Errorw("Error uploading DHCP UL flow into KV store", log.Fields{"flow": dhcpFlow, "error": err})
798 return
799 }
800 }
801
manikkaraj kbf256be2019-03-25 00:13:48 +0530802 return
803}
804
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700805// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530806func (f *OpenOltFlowMgr) addEAPOLFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, vlanID uint32, classifier map[string]interface{}, action map[string]interface{}) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700807 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 +0530808
809 uplinkClassifier := make(map[string]interface{})
810 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +0530811
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700812 var upstreamFlow openoltpb2.Flow
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530813 var networkIntfID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530814
815 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700816 uplinkClassifier[EthType] = uint32(EapEthType)
817 uplinkClassifier[PacketTagType] = SingleTag
818 uplinkClassifier[VlanVid] = vlanID
manikkaraj kbf256be2019-03-25 00:13:48 +0530819 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700820 uplinkAction[TrapToHost] = true
821 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
Girish Gowdra3d633032019-12-10 16:37:05 +0530822 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
823 log.Debug("Flow-exists--not-re-adding")
824 return
825 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530826 //Add Uplink EAPOL Flow
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530827 uplinkFlowID, err := f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530828 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700829 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manikkaraj k884c1242019-04-11 16:26:42 +0530830 return
manikkaraj kbf256be2019-03-25 00:13:48 +0530831 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700832 var classifierProto *openoltpb2.Classifier
833 var actionProto *openoltpb2.Action
834 log.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530835
836 if classifierProto = makeOpenOltClassifierField(uplinkClassifier); classifierProto == nil {
837 log.Error("Error in making classifier protobuf for ul flow")
838 return
839 }
840 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
841 if actionProto = makeOpenOltActionField(uplinkAction); actionProto == nil {
842 log.Error("Error in making action protobuf for ul flow")
843 return
844 }
845 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530846 networkIntfID, err = getNniIntfID(classifier, action)
847 if err != nil {
848 log.Error("Failed to get nniIntf ID")
849 return
850 }
851
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700852 upstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
853 OnuId: int32(onuID),
854 UniId: int32(uniID),
855 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700856 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700857 AllocId: int32(allocID),
858 NetworkIntfId: int32(networkIntfID),
859 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530860 Classifier: classifierProto,
861 Action: actionProto,
862 Priority: int32(logicalFlow.Priority),
863 Cookie: logicalFlow.Cookie,
864 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400865 if ok := f.addFlowToDevice(logicalFlow, &upstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530866 log.Debug("EAPOL UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400867 flowCategory := "EAPOL"
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530868 flowsToKVStore := f.getUpdatedFlowInfo(&upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
manikkaraj kbf256be2019-03-25 00:13:48 +0530869 if err := f.updateFlowInfoToKVStore(upstreamFlow.AccessIntfId,
870 upstreamFlow.OnuId,
871 upstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400872 upstreamFlow.FlowId,
873 /* lowCategory, */
874 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530875 log.Errorw("Error uploading EAPOL UL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
876 return
877 }
878 }
Girish Gowdra3d633032019-12-10 16:37:05 +0530879
manikkaraj kbf256be2019-03-25 00:13:48 +0530880 log.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
881}
882
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700883func makeOpenOltClassifierField(classifierInfo map[string]interface{}) *openoltpb2.Classifier {
884 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -0700885
886 classifier.EthType, _ = classifierInfo[EthType].(uint32)
887 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
888 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
889 vid := vlanID & VlanvIDMask
890 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -0400891 classifier.OVid = vid
892 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530893 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700894 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
895 vid := uint32(metadata)
896 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -0400897 classifier.IVid = vid
898 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530899 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700900 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400901 if vlanPcp == 0 {
902 classifier.OPbits = VlanPCPMask
903 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700904 classifier.OPbits = vlanPcp & VlanPCPMask
Manikkaraj kb1d51442019-07-23 10:41:02 -0400905 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530906 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700907 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
908 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
909 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
910 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
911 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
912 classifier.PktTagType = pktTagType
913
914 switch pktTagType {
915 case SingleTag:
916 case DoubleTag:
917 case Untagged:
918 default:
manikkaraj kbf256be2019-03-25 00:13:48 +0530919 log.Error("Invalid tag type in classifier") // should not hit
920 return nil
921 }
922 }
923 return &classifier
924}
925
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700926func makeOpenOltActionField(actionInfo map[string]interface{}) *openoltpb2.Action {
927 var actionCmd openoltpb2.ActionCmd
928 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +0530929 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700930 if _, ok := actionInfo[PopVlan]; ok {
931 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530932 action.Cmd.RemoveOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700933 } else if _, ok := actionInfo[PushVlan]; ok {
934 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530935 action.Cmd.AddOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700936 } else if _, ok := actionInfo[TrapToHost]; ok {
937 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +0530938 } else {
939 log.Errorw("Invalid-action-field", log.Fields{"action": actionInfo})
940 return nil
941 }
942 return &action
943}
944
Manikkaraj kb1d51442019-07-23 10:41:02 -0400945func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uni string, TpID uint32) string {
946 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530947}
948
Gamze Abakafee36392019-10-03 11:17:24 +0000949// DeleteTechProfileInstances removes the tech profile instances from persistent storage
950func (f *OpenOltFlowMgr) DeleteTechProfileInstances(intfID uint32, onuID uint32, uniID uint32, sn string) error {
951 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(intfID, onuID, uniID)
Devmalya Paul495b94a2019-08-27 19:42:00 -0400952 uniPortName := fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +0000953 for _, tpID := range tpIDList {
954 if err := f.DeleteTechProfileInstance(intfID, onuID, uniID, uniPortName, tpID); err != nil {
955 log.Debugw("Failed-to-delete-tp-instance-from-kv-store", log.Fields{"tp-id": tpID, "uni-port-name": uniPortName})
Girish Gowdra54934262019-11-13 14:19:55 +0530956 // return err
957 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +0000958 }
959 }
960 return nil
961}
962
963// DeleteTechProfileInstance removes the tech profile instance from persistent storage
964func (f *OpenOltFlowMgr) DeleteTechProfileInstance(intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
965 if uniPortName == "" {
966 uniPortName = fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
967 }
Devmalya Paul495b94a2019-08-27 19:42:00 -0400968 if err := f.techprofile[intfID].DeleteTechProfileInstance(tpID, uniPortName); err != nil {
969 log.Debugw("Failed-to-delete-tp-instance-from-kv-store", log.Fields{"tp-id": tpID, "uni-port-name": uniPortName})
970 return err
971 }
972 return nil
973}
974
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700975func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530976 if len(classifier) == 0 { // should never happen
977 log.Error("Invalid classfier object")
978 return 0
979 }
Girish Gowdra3d633032019-12-10 16:37:05 +0530980 log.Debugw("generating flow store cookie", log.Fields{"classifier": classifier, "gemPortID": gemPortID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530981 var jsonData []byte
982 var flowString string
983 var err error
984 // TODO: Do we need to marshall ??
985 if jsonData, err = json.Marshal(classifier); err != nil {
986 log.Error("Failed to encode classifier")
987 return 0
988 }
989 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700990 if gemPortID != 0 {
991 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +0530992 }
993 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700994 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +0530995 hash := big.NewInt(0)
996 hash.SetBytes(h.Sum(nil))
Girish Gowdra3d633032019-12-10 16:37:05 +0530997 generatedHash := hash.Uint64()
998 log.Debugw("hash generated", log.Fields{"hash": generatedHash})
999 return generatedHash
manikkaraj kbf256be2019-03-25 00:13:48 +05301000}
1001
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301002func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openoltpb2.Flow, flowStoreCookie uint64, flowCategory string, deviceFlowID uint32, logicalFlowID uint64) *[]rsrcMgr.FlowInfo {
1003 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001004 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001005 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1006 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1007 */
1008 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001009 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001010 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001011 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001012 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001013 // Get existing flows matching flowid for given subscriber from KV store
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301014 existingFlows := f.resourceMgr.GetFlowIDInfo(intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001015 if existingFlows != nil {
1016 log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001017 //for _, f := range *existingFlows {
1018 // flows = append(flows, f)
1019 //}
1020 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001021 }
1022 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 +05301023 return &flows
1024}
1025
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001026//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
1027// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
1028// var intfId uint32
1029// /* For flows which trap out of the NNI, the AccessIntfId is invalid
1030// (set to -1). In such cases, we need to refer to the NetworkIntfId .
1031// */
1032// if flow.AccessIntfId != -1 {
1033// intfId = uint32(flow.AccessIntfId)
1034// } else {
1035// intfId = uint32(flow.NetworkIntfId)
1036// }
1037// // Get existing flows matching flowid for given subscriber from KV store
1038// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
1039// if existingFlows != nil {
1040// log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
1041// for _, f := range *existingFlows {
1042// flows = append(flows, f)
1043// }
1044// }
1045// log.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
1046// return &flows
1047//}
1048
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001049func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
manikkaraj k17652a72019-05-06 09:06:36 -04001050 log.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001051 if err := f.resourceMgr.UpdateFlowIDInfo(intfID, onuID, uniID, flowID, flows); err != nil {
manikkaraj k17652a72019-05-06 09:06:36 -04001052 log.Debug("Error while Storing flow into KV store")
1053 return err
1054 }
1055 log.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +05301056 return nil
1057}
1058
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001059func (f *OpenOltFlowMgr) addFlowToDevice(logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) bool {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001060
1061 var intfID uint32
1062 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1063 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1064 */
1065 if deviceFlow.AccessIntfId != -1 {
1066 intfID = uint32(deviceFlow.AccessIntfId)
1067 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001068 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001069 intfID = uint32(deviceFlow.NetworkIntfId)
1070 }
1071
manikkaraj kbf256be2019-03-25 00:13:48 +05301072 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1073 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001074
1075 st, _ := status.FromError(err)
1076 if st.Code() == codes.AlreadyExists {
Gamze Abakafee36392019-10-03 11:17:24 +00001077 log.Debug("Flow already exists", log.Fields{"err": err, "deviceFlow": deviceFlow})
Girish Gowdra3d633032019-12-10 16:37:05 +05301078 return true
manikkaraj kbf256be2019-03-25 00:13:48 +05301079 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001080
1081 if err != nil {
1082 log.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": deviceFlow})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001083 f.resourceMgr.FreeFlowID(intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001084 return false
1085 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001086 f.registerFlow(logicalFlow, deviceFlow)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301087 log.Debugw("Flow added to device successfully ", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001088 return true
1089}
1090
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001091func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) bool {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001092 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1093 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1094 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001095 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
1096 log.Warnw("Can not remove flow from device since it's unreachable", log.Fields{"err": err, "deviceFlow": deviceFlow})
1097 //Assume the flow is removed
1098 return true
1099 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001100 log.Errorw("Failed to Remove flow from device", log.Fields{"err": err, "deviceFlow": deviceFlow})
1101 return false
serkant.uluderya245caba2019-09-24 23:15:29 -07001102
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001103 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001104 log.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301105 return true
1106}
1107
1108/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1109 //update core flows_proxy : flows_proxy.update('/', flows)
1110}
1111
1112func generateStoredId(flowId uint32, direction string)uint32{
1113
David K. Bainbridge82efc492019-09-04 09:57:11 -07001114 if direction == Upstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301115 log.Debug("Upstream flow shifting flowid")
1116 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001117 }else if direction == Downstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301118 log.Debug("Downstream flow not shifting flowid")
1119 return flowId
1120 }else{
1121 log.Errorw("Unrecognized direction",log.Fields{"direction": direction})
1122 return flowId
1123 }
1124}
1125
1126*/
1127
Humera Kouser94d7a842019-08-25 19:04:32 -04001128func (f *OpenOltFlowMgr) addLLDPFlow(flow *ofp.OfpFlowStats, portNo uint32) {
1129
1130 classifierInfo := make(map[string]interface{})
1131 actionInfo := make(map[string]interface{})
1132
1133 classifierInfo[EthType] = uint32(LldpEthType)
1134 classifierInfo[PacketTagType] = Untagged
1135 actionInfo[TrapToHost] = true
1136
1137 // LLDP flow is installed to trap LLDP packets on the NNI port.
1138 // We manage flow_id resource pool on per PON port basis.
1139 // Since this situation is tricky, as a hack, we pass the NNI port
1140 // index (network_intf_id) as PON port Index for the flow_id resource
1141 // pool. Also, there is no ONU Id available for trapping LLDP packets
1142 // on NNI port, use onu_id as -1 (invalid)
1143 // ****************** CAVEAT *******************
1144 // This logic works if the NNI Port Id falls within the same valid
1145 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1146 // we need to have a re-look at this.
1147 // *********************************************
1148
1149 var onuID = -1
1150 var uniID = -1
1151 var gemPortID = -1
1152
1153 var networkInterfaceID = IntfIDFromNniPortNum(portNo)
1154 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301155 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Humera Kouser94d7a842019-08-25 19:04:32 -04001156 log.Debug("Flow-exists--not-re-adding")
1157 return
1158 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301159 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001160
1161 if err != nil {
1162 log.Errorw("Flow id unavailable for LLDP traponNNI flow", log.Fields{"error": err})
1163 return
1164 }
1165 var classifierProto *openoltpb2.Classifier
1166 var actionProto *openoltpb2.Action
1167 if classifierProto = makeOpenOltClassifierField(classifierInfo); classifierProto == nil {
1168 log.Error("Error in making classifier protobuf for LLDP trap on nni flow")
1169 return
1170 }
1171 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1172 if actionProto = makeOpenOltActionField(actionInfo); actionProto == nil {
1173 log.Error("Error in making action protobuf for LLDP trap on nni flow")
1174 return
1175 }
1176 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
1177
1178 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1179 OnuId: int32(onuID), // OnuId not required
1180 UniId: int32(uniID), // UniId not used
1181 FlowId: flowID,
1182 FlowType: Downstream,
1183 NetworkIntfId: int32(networkInterfaceID),
1184 GemportId: int32(gemPortID),
1185 Classifier: classifierProto,
1186 Action: actionProto,
1187 Priority: int32(flow.Priority),
1188 Cookie: flow.Cookie,
1189 PortNo: portNo}
1190 if ok := f.addFlowToDevice(flow, &downstreamflow); ok {
1191 log.Debug("LLDP trap on NNI flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301192 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID, flow.Id)
Humera Kouser94d7a842019-08-25 19:04:32 -04001193 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1194 int32(onuID),
1195 int32(uniID),
1196 flowID, flowsToKVStore); err != nil {
1197 log.Errorw("Error uploading LLDP flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1198 }
1199 }
1200 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301201}
1202
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301203func getUniPortPath(intfID uint32, onuID int32, uniID int32) string {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001204 return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1205}
1206
1207//getOnuChildDevice to fetch onu
1208func (f *OpenOltFlowMgr) getOnuChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
1209 log.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
1210 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
1211 onuDevice := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301212 if onuDevice == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001213 log.Errorw("onu not found", log.Fields{"intfId": parentPortNo, "onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301214 return nil, errors.New("onu not found")
manikkaraj kbf256be2019-03-25 00:13:48 +05301215 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301216 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1217 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301218}
1219
1220func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001221 log.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301222 return nil
1223}
1224
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001225func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
1226 log.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301227}
1228
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001229func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001230 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001231 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001232 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001233 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001234}
1235
Girish Gowdra6b130582019-11-20 16:45:20 +05301236func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1237 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
1238 if err != nil {
1239 log.Errorw("error fetching child device from core", log.Fields{"onuId": onuID})
1240 return err
1241 }
1242
1243 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
1244 log.Debugw("sending gem port delete to openonu adapter", log.Fields{"msg": *delGemPortMsg})
1245 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1246 delGemPortMsg,
1247 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
1248 f.deviceHandler.deviceType,
1249 onuDevice.Type,
1250 onuDevice.Id,
1251 onuDevice.ProxyAddress.DeviceId, ""); sendErr != nil {
1252 log.Errorw("failure sending del gem port to onu adapter", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1253 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1254 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1255 return sendErr
1256 }
1257 log.Debugw("success sending del gem port to onu adapter", log.Fields{"msg": delGemPortMsg})
1258 return nil
1259}
1260
1261func (f *OpenOltFlowMgr) sendDeleteTcontToChild(intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1262 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
1263 if err != nil {
1264 log.Errorw("error fetching child device from core", log.Fields{"onuId": onuID})
1265 return err
1266 }
1267
1268 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
1269 log.Debugw("sending tcont delete to openonu adapter", log.Fields{"msg": *delTcontMsg})
1270 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1271 delTcontMsg,
1272 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
1273 f.deviceHandler.deviceType,
1274 onuDevice.Type,
1275 onuDevice.Id,
1276 onuDevice.ProxyAddress.DeviceId, ""); sendErr != nil {
1277 log.Errorw("failure sending del tcont to onu adapter", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1278 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1279 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1280 return sendErr
1281 }
1282 log.Debugw("success sending del tcont to onu adapter", log.Fields{"msg": delTcontMsg})
1283 return nil
1284}
1285
Girish Gowdra3d633032019-12-10 16:37:05 +05301286func (f *OpenOltFlowMgr) deletePendingFlows(Intf uint32, onuID int32, uniID int32) {
1287 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1288 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); ok {
1289 if val.(int) > 0 {
1290 pnFlDels := val.(int) - 1
1291 if pnFlDels > 0 {
1292 log.Debugw("flow delete succeeded, more pending",
1293 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID, "currPendingFlowCnt": pnFlDels})
1294 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1295 } else {
1296 log.Debugw("all pending flow deletes handled, removing entry from map",
1297 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1298 f.pendingFlowDelete.Delete(pnFlDelKey)
1299 }
1300 }
1301 } else {
1302 log.Debugw("no pending delete flows found",
1303 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1304
1305 }
1306
1307}
1308
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301309//clearResources clears pon resources in kv store and the device
1310func (f *OpenOltFlowMgr) clearResources(flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
1311 gemPortID int32, flowID uint32, flowDirection string,
1312 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001313
Chaitrashree G S90a17952019-11-14 21:51:21 -05001314 tpID, err := getTpIDFromFlow(flow)
1315 if err != nil {
1316 log.Error("metadata-is-not-present-invalid-flow-to-process", log.Fields{"pon": Intf, "onuID": onuID, "uniID": uniID})
1317 return err
1318 }
Gamze Abakafee36392019-10-03 11:17:24 +00001319
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001320 if len(updatedFlows) >= 0 {
1321 // There are still flows referencing the same flow_id.
1322 // So the flow should not be freed yet.
1323 // For ex: Case of HSIA where same flow is shared
1324 // between DS and US.
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301325 f.updateFlowInfoToKVStore(int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001326 if len(updatedFlows) == 0 {
Girish Gowdra3d633032019-12-10 16:37:05 +05301327 // Do this for subscriber flows only (not trap from NNI flows)
1328 if onuID != -1 && uniID != -1 {
1329 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1330 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
1331 log.Debugw("creating entry for pending flow delete",
1332 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1333 f.pendingFlowDelete.Store(pnFlDelKey, 1)
1334 } else {
1335 pnFlDels := val.(int) + 1
1336 log.Debugw("updating flow delete entry",
1337 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID, "currPendingFlowCnt": pnFlDels})
1338 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1339 }
1340
1341 defer f.deletePendingFlows(Intf, onuID, uniID)
1342 }
1343
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301344 log.Debugw("Releasing flow Id to resource manager", log.Fields{"Intf": Intf, "onuId": onuID, "uniId": uniID, "flowId": flowID})
1345 f.resourceMgr.FreeFlowID(Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001346
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301347 uni := getUniPortPath(Intf, onuID, uniID)
1348 tpPath := f.getTPpath(Intf, uni, tpID)
Gamze Abakafee36392019-10-03 11:17:24 +00001349 log.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301350 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(tpID, tpPath)
Gamze Abakafee36392019-10-03 11:17:24 +00001351 if err != nil { // This should not happen, something wrong in KV backend transaction
1352 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": 20, "path": tpPath})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301353 return err
Gamze Abakafee36392019-10-03 11:17:24 +00001354 }
1355 if techprofileInst == nil {
1356 log.Errorw("Tech-profile-instance-does-not-exist-in-KV Store", log.Fields{"tpPath": tpPath})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301357 return err
Gamze Abakafee36392019-10-03 11:17:24 +00001358 }
1359
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301360 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00001361 if f.isGemPortUsedByAnotherFlow(gemPK) {
1362 flowIDs := f.flowsUsedByGemPort[gemPK]
1363 for i, flowIDinMap := range flowIDs {
1364 if flowIDinMap == flowID {
1365 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301366 // everytime flowsUsedByGemPort cache is updated the same should be updated
1367 // in kv store by calling UpdateFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001368 f.flowsUsedByGemPort[gemPK] = flowIDs
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301369 f.resourceMgr.UpdateFlowIDsForGem(Intf, uint32(gemPortID), flowIDs)
Gamze Abakafee36392019-10-03 11:17:24 +00001370 break
1371 }
1372 }
1373 log.Debugw("Gem port id is still used by other flows", log.Fields{"gemPortID": gemPortID, "usedByFlows": flowIDs})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301374 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00001375 }
Gamze Abakafee36392019-10-03 11:17:24 +00001376 log.Debugf("Gem port id %d is not used by another flow - releasing the gem port", gemPortID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301377 f.resourceMgr.RemoveGemPortIDForOnu(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001378 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1379 // But it is anyway eventually removed later when the TechProfile is freed, so not a big issue for now.
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301380 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(uint32(gemPortID), Intf)
Gamze Abakafee36392019-10-03 11:17:24 +00001381 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301382 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1383 // by calling DeleteFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001384 delete(f.flowsUsedByGemPort, gemPK)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301385 f.resourceMgr.DeleteFlowIDsForGem(Intf, uint32(gemPortID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301386 f.resourceMgr.FreeGemPortID(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001387 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05301388 // Delete the gem port on the ONU.
1389 if err := f.sendDeleteGemPortToChild(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
1390 log.Errorw("error processing delete gem-port towards onu",
1391 log.Fields{"err": err, "pon": Intf, "onuID": onuID, "uniID": uniID, "gemPortId": gemPortID})
1392 }
Gamze Abakafee36392019-10-03 11:17:24 +00001393
Girish Gowdra54934262019-11-13 14:19:55 +05301394 ok, _ := f.isTechProfileUsedByAnotherGem(Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001395 if !ok {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301396 f.resourceMgr.RemoveTechProfileIDForOnu(Intf, uint32(onuID), uint32(uniID), tpID)
1397 f.RemoveSchedulerQueues(schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1398 f.RemoveSchedulerQueues(schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1399 f.DeleteTechProfileInstance(Intf, uint32(onuID), uint32(uniID), "", tpID)
1400 f.resourceMgr.FreeAllocID(Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301401 // Delete the TCONT on the ONU.
1402 if err := f.sendDeleteTcontToChild(Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
1403 log.Errorw("error processing delete tcont towards onu",
1404 log.Fields{"pon": Intf, "onuID": onuID, "uniID": uniID, "allocId": techprofileInst.UsScheduler.AllocID})
1405 }
Gamze Abakafee36392019-10-03 11:17:24 +00001406 }
1407 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001408 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301409 return nil
1410}
1411
1412func (f *OpenOltFlowMgr) clearFlowFromResourceManager(flow *ofp.OfpFlowStats, flowDirection string) {
1413
1414 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowDirection": flowDirection, "flow": *flow})
1415 var updatedFlows []rsrcMgr.FlowInfo
1416 var flowID uint32
1417 var onuID, uniID int32
1418 classifierInfo := make(map[string]interface{})
1419
1420 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
1421 if err != nil {
1422 log.Error(err)
1423 return
1424 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301425
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301426 onuID = int32(onu)
1427 uniID = int32(uni)
1428
1429 for _, field := range flows.GetOfbFields(flow) {
1430 if field.Type == flows.IP_PROTO {
1431 classifierInfo[IPProto] = field.GetIpProto()
1432 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
1433 }
1434 }
1435 log.Debugw("Extracted access info from flow to be deleted",
1436 log.Fields{"ponIntf": Intf, "onuID": onuID, "uniID": uniID})
1437
1438 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1439 onuID = -1
1440 uniID = -1
1441 log.Debug("Trap on nni flow set oni, uni to -1")
1442 Intf = IntfIDFromNniPortNum(inPort)
1443 }
1444 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(Intf, onuID, uniID)
1445 for _, flowID = range flowIds {
1446 flowInfo := f.resourceMgr.GetFlowIDInfo(Intf, onuID, uniID, flowID)
1447 if flowInfo == nil {
1448 log.Debugw("No FlowInfo found found in KV store",
1449 log.Fields{"Intf": Intf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1450 return
1451 }
1452 updatedFlows = nil
1453 for _, flow := range *flowInfo {
1454 updatedFlows = append(updatedFlows, flow)
1455 }
1456
1457 for i, storedFlow := range updatedFlows {
1458 if flow.Id == storedFlow.LogicalFlowID {
1459 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
1460 log.Debugw("Flow to be deleted", log.Fields{"flow": storedFlow})
1461 if ok := f.removeFlowFromDevice(&removeFlowMessage); ok {
1462 log.Debug("Flow removed from device successfully")
1463 //Remove the Flow from FlowInfo
1464 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1465 err = f.clearResources(flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
1466 flowID, flowDirection, portNum, updatedFlows)
1467 if err != nil {
1468 log.Error("Failed to clear resources for flow", log.Fields{"flow": storedFlow})
1469 return
1470 }
1471 } else {
1472 log.Error("Failed to remove flow from device")
1473 return
1474 }
1475 }
1476 }
1477 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001478}
1479
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001480//RemoveFlow removes the flow from the device
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001481func (f *OpenOltFlowMgr) RemoveFlow(flow *ofp.OfpFlowStats) {
1482 log.Debugw("Removing Flow", log.Fields{"flow": flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301483 var direction string
1484 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001485
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301486 for _, action := range flows.GetActions(flow) {
1487 if action.Type == flows.OUTPUT {
1488 if out := action.GetOutput(); out != nil {
1489 actionInfo[Output] = out.GetPort()
1490 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
1491 } else {
1492 log.Error("Invalid output port in action")
1493 return
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001494 }
1495 }
1496 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301497 if IsUpstream(actionInfo[Output].(uint32)) {
1498 direction = Upstream
1499 } else {
1500 direction = Downstream
1501 }
1502
1503 f.clearFlowFromResourceManager(flow, direction) //TODO: Take care of the limitations
1504
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001505 return
1506}
1507
Girish Gowdra3d633032019-12-10 16:37:05 +05301508func (f *OpenOltFlowMgr) waitForFlowDeletesToCompleteForOnu(ctx context.Context, intfID uint32, onuID uint32,
1509 uniID uint32, ch chan bool) {
1510 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
1511 for {
1512 select {
1513 case <-time.After(20 * time.Millisecond):
1514 if flowDelRefCnt, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok || flowDelRefCnt == 0 {
1515 log.Debug("pending flow deletes completed")
1516 ch <- true
1517 return
1518 }
1519 case <-ctx.Done():
1520 log.Error("flow delete wait handler routine canceled")
1521 return
1522 }
1523 }
1524}
1525
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001526// AddFlow add flow to device
Manikkaraj kb1d51442019-07-23 10:41:02 -04001527func (f *OpenOltFlowMgr) AddFlow(flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001528 classifierInfo := make(map[string]interface{})
1529 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001530 var UsMeterID uint32
1531 var DsMeterID uint32
1532
1533 log.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001534 formulateClassifierInfoFromFlow(classifierInfo, flow)
1535
1536 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
1537 if err != nil {
1538 // Error logging is already done in the called function
1539 // So just return in case of error
1540 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301541 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001542
manikkaraj k17652a72019-05-06 09:06:36 -04001543 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00001544 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
1545 if err != nil {
1546 // error if any, already logged in the called function
1547 return
manikkaraj k17652a72019-05-06 09:06:36 -04001548 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001549
David K. Bainbridge82efc492019-09-04 09:57:11 -07001550 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[Output]})
1551 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00001552
Humera Kouser94d7a842019-08-25 19:04:32 -04001553 if ethType, ok := classifierInfo[EthType]; ok {
1554 if ethType.(uint32) == LldpEthType {
1555 log.Info("Adding LLDP flow")
1556 f.addLLDPFlow(flow, portNo)
1557 return
1558 }
1559 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001560 if ipProto, ok := classifierInfo[IPProto]; ok {
1561 if ipProto.(uint32) == IPProtoDhcp {
1562 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001563 if udpSrc.(uint32) == uint32(67) {
1564 log.Debug("trap-dhcp-from-nni-flow")
1565 f.addDHCPTrapFlowOnNNI(flow, classifierInfo, portNo)
1566 return
1567 }
1568 }
1569 }
1570 }
A R Karthick1f85b802019-10-11 05:06:05 +00001571
1572 f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301573 f.resourceMgr.AddUniPortToOnuInfo(intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00001574
Chaitrashree G S90a17952019-11-14 21:51:21 -05001575 TpID, err := getTpIDFromFlow(flow)
1576 if err != nil {
1577 log.Error("metadata-is-not-present-invalid-flow-to-process", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1578 return
1579 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001580 log.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001581 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07001582 UsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001583 log.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
1584 } else {
Scott Baker355d1742019-10-24 10:57:52 -07001585 DsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001586 log.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
1587
1588 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301589
1590 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
1591 if _, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
1592 log.Debugw("no pending flows found, going ahead with flow install", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1593 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
1594 } else {
1595 ctx := context.Background()
1596 ctx, cancel := context.WithCancel(ctx)
1597 defer cancel()
1598 pendingFlowDelComplete := make(chan bool)
1599 go f.waitForFlowDeletesToCompleteForOnu(ctx, intfID, onuID, uniID, pendingFlowDelComplete)
1600 select {
1601 case <-pendingFlowDelComplete:
1602 log.Debugw("all pending flow deletes completed", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1603 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
1604
1605 case <-time.After(10 * time.Second):
1606 log.Errorw("pending flow deletes not completed after timeout", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1607 }
1608 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001609}
1610
1611//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04001612func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001613
1614 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301615 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001616 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301617 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301618 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301619 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04001620
Manikkaraj kb1d51442019-07-23 10:41:02 -04001621 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001622 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
manikkaraj k17652a72019-05-06 09:06:36 -04001623 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
1624 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1625 tpDownloadMsg,
1626 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
1627 f.deviceHandler.deviceType,
1628 onuDevice.Type,
1629 onuDevice.Id,
1630 onuDevice.ProxyAddress.DeviceId, "")
1631 if sendErr != nil {
1632 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1633 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1634 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1635 return sendErr
1636 }
1637 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05301638 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301639}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001640
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301641//UpdateOnuInfo function adds onu info to cache and kvstore
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001642func (f *OpenOltFlowMgr) UpdateOnuInfo(intfID uint32, onuID uint32, serialNum string) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301643
1644 f.lockCache.Lock()
1645 defer f.lockCache.Unlock()
1646 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
1647 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
1648 if err := f.resourceMgr.AddOnuInfo(intfID, onu); err != nil {
1649 log.Errorw("failed to add onu info", log.Fields{"onu": onu})
1650 return
1651 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001652 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
1653}
1654
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301655//addGemPortToOnuInfoMap function adds GEMport to ONU map
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001656func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(intfID uint32, onuID uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301657 f.lockCache.Lock()
1658 defer f.lockCache.Unlock()
1659 onugem := f.onuGemInfo[intfID]
1660 // update the gem to the local cache as well as to kv strore
1661 for idx, onu := range onugem {
1662 if onu.OnuID == onuID {
1663 // check if gem already exists , else update the cache and kvstore
1664 for _, gem := range onu.GemPorts {
1665 if gem == gemPort {
1666 log.Debugw("Gem already in cache, no need to update cache and kv store",
1667 log.Fields{"gem": gemPort})
1668 return
1669 }
1670 }
1671 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
1672 f.onuGemInfo[intfID] = onugem
1673 }
1674 }
1675 err := f.resourceMgr.AddGemToOnuGemInfo(intfID, onuID, gemPort)
1676 if err != nil {
1677 log.Errorw("Failed to add gem to onu", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001678 return
1679 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001680}
1681
1682// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001683
1684//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
1685func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301686
1687 f.lockCache.Lock()
1688 defer f.lockCache.Unlock()
1689
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001690 log.Debugw("Getting ONU ID from GEM port and PON port", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPortId": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301691 // get onuid from the onugem info cache
1692 onugem := f.onuGemInfo[intfID]
1693 for _, onu := range onugem {
1694 for _, gem := range onu.GemPorts {
1695 if gem == gemPortID {
1696 return onu.OnuID, nil
1697 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001698 }
1699 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001700 log.Errorw("onuid is not found", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPort": gemPortID})
1701 return uint32(0), errors.New("key error, onuid is not found") // ONU ID 0 is not a valid one
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001702}
1703
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001704//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
1705func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001706 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001707 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001708 var err error
1709
1710 if packetIn.IntfType == "pon" {
1711 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001712 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001713 log.Errorw("Unable to get ONU ID from GEM/PON port", log.Fields{"pon port": packetIn.IntfId, "gemport": packetIn.GemportId})
1714 return logicalPortNum, err
1715 }
1716 if packetIn.PortNo != 0 {
1717 logicalPortNum = packetIn.PortNo
1718 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001719 uniID := uint32(0) // FIXME - multi-uni support
1720 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001721 }
1722 // Store the gem port through which the packet_in came. Use the same gem port for packet_out
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301723 f.UpdateGemPortForPktIn(packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001724 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001725 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001726 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001727 log.Debugw("Retrieved logicalport from packet-in", log.Fields{
1728 "logicalPortNum": logicalPortNum,
1729 "IntfType": packetIn.IntfType,
1730 "packet": hex.EncodeToString(packetIn.Pkt),
1731 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001732 return logicalPortNum, nil
1733}
1734
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001735//GetPacketOutGemPortID returns gemPortId
1736func (f *OpenOltFlowMgr) GetPacketOutGemPortID(intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
1737 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001738 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301739
1740 f.lockCache.Lock()
1741 defer f.lockCache.Unlock()
1742 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum}
1743
1744 gemPortID, ok := f.packetInGemPort[pktInkey]
1745 if ok {
1746 log.Debugw("Found gemport for pktin key", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1747 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001748 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301749 //If gem is not found in cache try to get it from kv store, if found in kv store, update the cache and return.
1750 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(intfID, onuID, portNum)
1751 if err == nil {
1752 if gemPortID != 0 {
1753 f.packetInGemPort[pktInkey] = gemPortID
1754 log.Debugw("Found gem port from kv store and updating cache with gemport",
1755 log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1756 return gemPortID, nil
1757 }
1758 }
1759 log.Errorw("Failed to get gemport", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1760 return uint32(0), err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001761}
1762
Manikkaraj kb1d51442019-07-23 10:41:02 -04001763func installFlowOnAllGemports(
1764 f1 func(intfId uint32, onuId uint32, uniId uint32,
1765 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
1766 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32),
1767 f2 func(intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301768 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
1769 classifier map[string]interface{}, action map[string]interface{}),
Manikkaraj kb1d51442019-07-23 10:41:02 -04001770 args map[string]uint32,
1771 classifier map[string]interface{}, action map[string]interface{},
1772 logicalFlow *ofp.OfpFlowStats,
1773 gemPorts []uint32,
1774 FlowType string,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001775 vlanID ...uint32) {
1776 log.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
1777 for _, gemPortID := range gemPorts {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001778 if FlowType == HsiaFlow || FlowType == DhcpFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001779 f1(args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001780 } else if FlowType == EapolFlow {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301781 f2(args["intfId"], args["onuId"], args["uniId"], args["portNo"], logicalFlow, args["allocId"], gemPortID, vlanID[0], classifier, action)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001782 } else {
1783 log.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
1784 return
1785 }
1786 }
1787}
1788
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001789func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
1790 log.Debug("Adding trap-dhcp-of-nni-flow")
1791 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001792 classifier[PacketTagType] = DoubleTag
1793 action[TrapToHost] = true
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301794 var err error
1795 var networkInterfaceID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001796 /* We manage flowId resource pool on per PON port basis.
1797 Since this situation is tricky, as a hack, we pass the NNI port
1798 index (network_intf_id) as PON port Index for the flowId resource
1799 pool. Also, there is no ONU Id available for trapping DHCP packets
1800 on NNI port, use onu_id as -1 (invalid)
1801 ****************** CAVEAT *******************
1802 This logic works if the NNI Port Id falls within the same valid
1803 range of PON Port Ids. If this doesn't work for some OLT Vendor
1804 we need to have a re-look at this.
1805 *********************************************
1806 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001807 onuID := -1
1808 uniID := -1
1809 gemPortID := -1
1810 allocID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301811 networkInterfaceID, err = getNniIntfID(classifier, action)
1812 if err != nil {
1813 log.Error("Failed to get nniIntf ID")
1814 return
1815 }
1816
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001817 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301818 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001819 log.Debug("Flow-exists--not-re-adding")
1820 return
1821 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301822 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001823 if err != nil {
1824 log.Errorw("Flow id unavailable for DHCP traponNNI flow", log.Fields{"error": err})
1825 return
1826 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001827 var classifierProto *openoltpb2.Classifier
1828 var actionProto *openoltpb2.Action
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001829 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
1830 log.Error("Error in making classifier protobuf for dhcp trap on nni flow")
1831 return
1832 }
1833 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1834 if actionProto = makeOpenOltActionField(action); actionProto == nil {
1835 log.Error("Error in making action protobuf for dhcp trap on nni flow")
1836 return
1837 }
1838 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001839 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1840 OnuId: int32(onuID), // OnuId not required
1841 UniId: int32(uniID), // UniId not used
1842 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001843 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001844 AllocId: int32(allocID), // AllocId not used
1845 NetworkIntfId: int32(networkInterfaceID),
1846 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001847 Classifier: classifierProto,
1848 Action: actionProto,
1849 Priority: int32(logicalFlow.Priority),
1850 Cookie: logicalFlow.Cookie,
1851 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001852 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001853 log.Debug("DHCP trap on NNI flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301854 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001855 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1856 int32(onuID),
1857 int32(uniID),
1858 flowID, flowsToKVStore); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001859 log.Errorw("Error uploading DHCP DL flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1860 }
1861 }
1862 return
1863}
salmansiddiqui7ac62132019-08-22 03:58:50 +00001864
1865func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
1866 if MeterID == 0 { // This should never happen
1867 log.Error("Invalid meter id")
1868 return "", errors.New("invalid meter id")
1869 }
1870 if Dir == tp_pb.Direction_UPSTREAM {
1871 return "upstream", nil
1872 } else if Dir == tp_pb.Direction_DOWNSTREAM {
1873 return "downstream", nil
1874 }
1875 return "", nil
1876}
1877
1878func (f *OpenOltFlowMgr) checkAndAddFlow(args map[string]uint32, classifierInfo map[string]interface{},
Gamze Abakafee36392019-10-03 11:17:24 +00001879 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst *tp.TechProfile, gemPorts []uint32,
1880 TpID uint32, uni string) {
1881 var gemPort uint32
1882 intfID := args[IntfID]
1883 onuID := args[OnuID]
1884 uniID := args[UniID]
1885 portNo := args[PortNo]
1886 allocID := TpInst.UsScheduler.AllocID
salmansiddiqui7ac62132019-08-22 03:58:50 +00001887 if ipProto, ok := classifierInfo[IPProto]; ok {
1888 if ipProto.(uint32) == IPProtoDhcp {
1889 log.Info("Adding DHCP flow")
1890 if pcp, ok := classifierInfo[VlanPcp]; ok {
1891 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1892 tp_pb.Direction_UPSTREAM,
1893 pcp.(uint32))
1894 //Adding DHCP upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001895 f.addDHCPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001896 } else {
1897 //Adding DHCP upstream flow to all gemports
1898 installFlowOnAllGemports(f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, DhcpFlow)
1899 }
1900
1901 } else if ipProto == IgmpProto {
1902 log.Info("igmp flow add ignored, not implemented yet")
1903 return
1904 } else {
1905 log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
1906 return
1907 }
1908 } else if ethType, ok := classifierInfo[EthType]; ok {
1909 if ethType.(uint32) == EapEthType {
1910 log.Info("Adding EAPOL flow")
1911 var vlanID uint32
1912 if val, ok := classifierInfo[VlanVid]; ok {
1913 vlanID = (val.(uint32)) & VlanvIDMask
1914 } else {
1915 vlanID = DefaultMgmtVlan
1916 }
1917 if pcp, ok := classifierInfo[VlanPcp]; ok {
1918 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1919 tp_pb.Direction_UPSTREAM,
1920 pcp.(uint32))
1921
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301922 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID, gemPort, vlanID, classifierInfo, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001923 } else {
1924 installFlowOnAllGemports(nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, EapolFlow, vlanID)
1925 }
1926 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001927 } else if _, ok := actionInfo[PushVlan]; ok {
1928 log.Info("Adding upstream data rule")
1929 if pcp, ok := classifierInfo[VlanPcp]; ok {
1930 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1931 tp_pb.Direction_UPSTREAM,
1932 pcp.(uint32))
1933 //Adding HSIA upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001934 f.addUpstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001935 } else {
1936 //Adding HSIA upstream flow to all gemports
1937 installFlowOnAllGemports(f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1938 }
1939 } else if _, ok := actionInfo[PopVlan]; ok {
1940 log.Info("Adding Downstream data rule")
1941 if pcp, ok := classifierInfo[VlanPcp]; ok {
1942 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05001943 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001944 pcp.(uint32))
1945 //Adding HSIA downstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001946 f.addDownstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001947 } else {
1948 //Adding HSIA downstream flow to all gemports
1949 installFlowOnAllGemports(f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1950 }
1951 } else {
1952 log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
1953 return
1954 }
1955 // Send Techprofile download event to child device in go routine as it takes time
1956 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, TpID)
1957}
1958
Gamze Abakafee36392019-10-03 11:17:24 +00001959func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
1960 flowIDList := f.flowsUsedByGemPort[gemPK]
1961 if len(flowIDList) > 1 {
1962 return true
1963 }
1964 return false
1965}
1966
Girish Gowdra54934262019-11-13 14:19:55 +05301967func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
Gamze Abakafee36392019-10-03 11:17:24 +00001968 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ponIntf, onuID, uniID)
1969 tpGemPorts := tpInst.UpstreamGemPortAttributeList
1970 for _, currentGemPort := range currentGemPorts {
1971 for _, tpGemPort := range tpGemPorts {
1972 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
1973 return true, currentGemPort
1974 }
1975 }
1976 }
Girish Gowdra54934262019-11-13 14:19:55 +05301977 if tpInst.InstanceCtrl.Onu == "single-instance" {
1978 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
1979 f.resourceMgr.RemoveTechProfileIDForOnu(ponIntf, uint32(onuID), uint32(uniID), tpID)
1980 f.DeleteTechProfileInstance(ponIntf, uint32(onuID), uint32(uniID), "", tpID)
1981
1982 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
1983 // still be used on other uni ports.
1984 // So, we need to check and make sure that no other gem port is referring to the given TP ID
1985 // on any other uni port.
1986 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(tpID, ponIntf, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301987 log.Debugw("got single instance tp instances", log.Fields{"tpInstances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05301988 for i := 0; i < len(tpInstances); i++ {
1989 tpI := tpInstances[i]
1990 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05301991 for _, tpGemPort := range tpGemPorts {
1992 if tpGemPort.GemportID != gemPortID {
1993 log.Debugw("single instance tp is in use by gem", log.Fields{"gemPort": tpGemPort.GemportID})
1994 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05301995 }
1996 }
1997 }
1998 }
Girish Gowdra6b130582019-11-20 16:45:20 +05301999 log.Debug("tech profile is not in use by any gem")
Gamze Abakafee36392019-10-03 11:17:24 +00002000 return false, 0
2001}
2002
salmansiddiqui7ac62132019-08-22 03:58:50 +00002003func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002004 for _, field := range flows.GetOfbFields(flow) {
2005 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002006 classifierInfo[EthType] = field.GetEthType()
2007 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002008 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002009 classifierInfo[IPProto] = field.GetIpProto()
2010 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002011 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002012 classifierInfo[InPort] = field.GetPort()
2013 log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002014 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05302015 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
salmansiddiqui7ac62132019-08-22 03:58:50 +00002016 log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002017 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002018 classifierInfo[VlanPcp] = field.GetVlanPcp()
2019 log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002020 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002021 classifierInfo[UDPDst] = field.GetUdpDst()
2022 log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002023 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002024 classifierInfo[UDPSrc] = field.GetUdpSrc()
2025 log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002026 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002027 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
2028 log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002029 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002030 classifierInfo[Ipv4Src] = field.GetIpv4Src()
2031 log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002032 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002033 classifierInfo[Metadata] = field.GetTableMetadata()
2034 log.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07002035 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002036 classifierInfo[TunnelID] = field.GetTunnelId()
2037 log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
2038 } else {
2039 log.Errorw("Un supported field type", log.Fields{"type": field.Type})
2040 return
2041 }
2042 }
2043}
2044
2045func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07002046 for _, action := range flows.GetActions(flow) {
2047 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002048 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002049 actionInfo[Output] = out.GetPort()
2050 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002051 } else {
2052 log.Error("Invalid output port in action")
2053 return errors.New("invalid output port in action")
2054 }
Scott Baker355d1742019-10-24 10:57:52 -07002055 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002056 actionInfo[PopVlan] = true
2057 log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002058 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002059 if out := action.GetPush(); out != nil {
2060 if tpid := out.GetEthertype(); tpid != 0x8100 {
2061 log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
2062 } else {
2063 actionInfo[PushVlan] = true
2064 actionInfo[TPID] = tpid
2065 log.Debugw("action-type-push-vlan",
2066 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
2067 }
2068 }
Scott Baker355d1742019-10-24 10:57:52 -07002069 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002070 if out := action.GetSetField(); out != nil {
2071 if field := out.GetField(); field != nil {
2072 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
2073 log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
2074 return errors.New("invalid openflow class")
2075 }
2076 /*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
2077 if ofbField := field.GetOfbField(); ofbField != nil {
2078 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
2079 if vlan := ofbField.GetVlanVid(); vlan != 0 {
2080 actionInfo[VlanVid] = vlan & 0xfff
2081 log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
2082 } else {
2083 log.Error("No Invalid vlan id in set vlan-vid action")
2084 }
2085 } else {
2086 log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
2087 }
2088 }
2089 }
2090 }
2091 } else {
2092 log.Errorw("Un supported action type", log.Fields{"type": action.Type})
2093 return errors.New("un supported action type")
2094 }
2095 }
2096 return nil
2097}
2098
2099func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002100 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002101 log.Debug("Controller bound trap flows, getting inport from tunnelid")
2102 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2103 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002104 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002105 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07002106 log.Debugw("upstream pon-to-controller-flow,inport-in-tunnelid", log.Fields{"newInPort": classifierInfo[InPort].(uint32), "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002107 } else {
2108 log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
2109 return errors.New("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
2110 }
2111 }
2112 } else {
2113 log.Debug("Non-Controller flows, getting uniport from tunnelid")
2114 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07002115 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002116 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002117 actionInfo[Output] = uniPort
2118 log.Debugw("downstream-nni-to-pon-port-flow, outport-in-tunnelid", log.Fields{"newOutPort": actionInfo[Output].(uint32), "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002119 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002120 log.Debug("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid", log.Fields{"InPort": classifierInfo[InPort].(uint32), "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002121 return errors.New("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid")
2122 }
2123 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2124 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002125 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002126 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07002127 log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[Output].(uint32),
2128 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002129 } else {
2130 log.Debug("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid", log.Fields{"InPort": classifierInfo[InPort].(uint32),
David K. Bainbridge82efc492019-09-04 09:57:11 -07002131 "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002132 return errors.New("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid")
2133 }
2134 }
2135 }
2136 return nil
2137}
Gamze Abakafee36392019-10-03 11:17:24 +00002138
Chaitrashree G S90a17952019-11-14 21:51:21 -05002139func getTpIDFromFlow(flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00002140 /* Metadata 8 bytes:
2141 Most Significant 2 Bytes = Inner VLAN
2142 Next 2 Bytes = Tech Profile ID(TPID)
2143 Least Significant 4 Bytes = Port ID
2144 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
2145 subscriber related flows.
2146 */
2147 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
2148 if metadata == 0 {
Chaitrashree G S90a17952019-11-14 21:51:21 -05002149 log.Error("metadata-is-not-present-in-flow-which-is-mandatory")
2150 return 0, errors.New("metadata-is-not-present-in-flow-which-is-mandatory")
Gamze Abakafee36392019-10-03 11:17:24 +00002151 }
2152 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002153 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00002154}
2155
2156func appendUnique(slice []uint32, item uint32) []uint32 {
2157 for _, sliceElement := range slice {
2158 if sliceElement == item {
2159 return slice
2160 }
2161 }
2162 return append(slice, item)
2163}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302164
2165// getNniIntfID gets nni intf id from the flow classifier/action
2166func getNniIntfID(classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
2167
2168 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
2169 if portType == voltha.Port_PON_OLT {
2170 intfID := IntfIDFromNniPortNum(action[Output].(uint32))
2171 log.Debugw("output Nni IntfID is", log.Fields{"intfid": intfID})
2172 return intfID, nil
2173 } else if portType == voltha.Port_ETHERNET_NNI {
2174 intfID := IntfIDFromNniPortNum(classifier[InPort].(uint32))
2175 log.Debugw("input Nni IntfID is", log.Fields{"intfid": intfID})
2176 return intfID, nil
2177 }
2178 return uint32(0), nil
2179}
2180
2181// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
2182func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32) {
2183 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort}
2184
2185 f.lockCache.Lock()
2186 defer f.lockCache.Unlock()
2187 _, ok := f.packetInGemPort[pktInkey]
2188 if ok {
2189 log.Debugw("pktin key found in cache , no need to update kv as we are assuming both will be in sync",
2190 log.Fields{"pktinkey": pktInkey, "gem": gemPort})
2191 } else {
2192 f.packetInGemPort[pktInkey] = gemPort
2193
2194 f.resourceMgr.UpdateGemPortForPktIn(pktInkey, gemPort)
2195 log.Debugw("pktin key not found in local cache updating cache and kv store", log.Fields{"pktinkey": pktInkey, "gem": gemPort})
2196 }
2197 return
2198}
2199
2200// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
2201func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(intfID uint32, onuID uint32, portNum uint32) {
2202
2203 f.lockCache.Lock()
2204 defer f.lockCache.Unlock()
2205 onugem := f.onuGemInfo[intfID]
2206 for idx, onu := range onugem {
2207 if onu.OnuID == onuID {
2208 for _, uni := range onu.UniPorts {
2209 if uni == portNum {
2210 log.Debugw("uni already in cache, no need to update cache and kv store",
2211 log.Fields{"uni": portNum})
2212 return
2213 }
2214 }
2215 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
2216 f.onuGemInfo[intfID] = onugem
2217 }
2218 }
2219 f.resourceMgr.AddUniPortToOnuInfo(intfID, onuID, portNum)
2220}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302221
2222func (f *OpenOltFlowMgr) loadFlowIDlistForGem(intf uint32) {
2223 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(intf)
2224 if err != nil {
2225 log.Error("Failed to get flowid list per gem", log.Fields{"intf": intf})
2226 return
2227 }
2228 for gem, FlowIDs := range flowIDsList {
2229 gemPK := gemPortKey{intf, uint32(gem)}
2230 f.flowsUsedByGemPort[gemPK] = FlowIDs
2231 }
2232 return
2233}