blob: 71a085002f579070b68a46093a2e11f89cca98df [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 }
Gamze Abakafee36392019-10-03 11:17:24 +0000335 log.Debugw("Meter-does-not-exist-Creating-new", log.Fields{"MeterID": sq.meterID, "Direction": Direction})
336 if sq.direction == tp_pb.Direction_UPSTREAM {
337 SchedCfg = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
338 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
339 SchedCfg = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400340 }
341 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000342 if sq.flowMetadata != nil {
343 for _, meter := range sq.flowMetadata.Meters {
344 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400345 meterConfig = meter
346 log.Debugw("Found-meter-config-from-flowmetadata", log.Fields{"meterConfig": meterConfig})
347 break
348 }
349 }
350 } else {
351 log.Error("Flow-metadata-is-not-present-in-flow")
352 }
353 if meterConfig == nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000354 log.Errorw("Could-not-get-meterbands-from-flowMetadata", log.Fields{"flowMetadata": sq.flowMetadata,
355 "MeterID": sq.meterID})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000356 return errors.New("failed-to-get-meter-from-flowMetadata")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400357 } else if len(meterConfig.Bands) < MaxMeterBand {
Gamze Abakafee36392019-10-03 11:17:24 +0000358 log.Errorw("Invalid-number-of-bands-in-meter", log.Fields{"Bands": meterConfig.Bands, "MeterID": sq.meterID})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000359 return errors.New("invalid-number-of-bands-in-meter")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400360 }
361 cir := meterConfig.Bands[0].Rate
362 cbs := meterConfig.Bands[0].BurstSize
363 eir := meterConfig.Bands[1].Rate
364 ebs := meterConfig.Bands[1].BurstSize
365 pir := cir + eir
366 pbs := cbs + ebs
367 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
368
Gamze Abakafee36392019-10-03 11:17:24 +0000369 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Manikkaraj kb1d51442019-07-23 10:41:02 -0400370
371 log.Debugw("Sending Traffic scheduler create to device", log.Fields{"Direction": Direction, "TrafficScheds": TrafficSched})
372 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000373 IntfId: sq.intfID, OnuId: sq.onuID,
374 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400375 TrafficScheds: TrafficSched}); err != nil {
376 log.Errorw("Failed to create traffic schedulers", log.Fields{"error": err})
377 return err
378 }
379 // On receiving the CreateTrafficQueues request, the driver should create corresponding
380 // downstream queues.
Gamze Abakafee36392019-10-03 11:17:24 +0000381 trafficQueues := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400382 log.Debugw("Sending Traffic Queues create to device", log.Fields{"Direction": Direction, "TrafficQueues": trafficQueues})
383 if _, err := f.deviceHandler.Client.CreateTrafficQueues(context.Background(),
Gamze Abakafee36392019-10-03 11:17:24 +0000384 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
385 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400386 TrafficQueues: trafficQueues}); err != nil {
387 log.Errorw("Failed to create traffic queues in device", log.Fields{"error": err})
388 return err
389 }
390
salmansiddiqui7ac62132019-08-22 03:58:50 +0000391 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400392 * store the meter id on the KV store, for further reference.
393 */
Gamze Abakafee36392019-10-03 11:17:24 +0000394 if err := f.resourceMgr.UpdateMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterConfig); err != nil {
395 log.Error("Failed to update meter id for onu %d, meterid %d", sq.onuID, sq.meterID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400396 return err
397 }
398 log.Debugw("updated-meter-info into KV store successfully", log.Fields{"Direction": Direction,
399 "Meter": meterConfig})
400 return nil
401}
402
salmansiddiqui7ac62132019-08-22 03:58:50 +0000403// 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 +0000404func (f *OpenOltFlowMgr) RemoveSchedulerQueues(sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400405
406 var Direction string
407 var SchedCfg *tp_pb.SchedulerConfig
408 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000409 log.Debugw("Removing schedulers and Queues in OLT", log.Fields{"Direction": sq.direction, "IntfID": sq.intfID,
410 "OnuID": sq.onuID, "UniID": sq.uniID, "UniPort": sq.uniPort})
411 if sq.direction == tp_pb.Direction_UPSTREAM {
412 SchedCfg = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400413 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000414 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
415 SchedCfg = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400416 Direction = "downstream"
417 }
418
Gamze Abakafee36392019-10-03 11:17:24 +0000419 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400420 if err != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000421 log.Errorf("Failed to get Meter for Onu %d", sq.onuID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400422 return err
423 }
424 if KVStoreMeter == nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000425 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 -0400426 return nil
427 }
428 cir := KVStoreMeter.Bands[0].Rate
429 cbs := KVStoreMeter.Bands[0].BurstSize
430 eir := KVStoreMeter.Bands[1].Rate
431 ebs := KVStoreMeter.Bands[1].BurstSize
432 pir := cir + eir
433 pbs := cbs + ebs
434
435 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
436
Gamze Abakafee36392019-10-03 11:17:24 +0000437 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
438 TrafficQueues := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400439
440 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(context.Background(),
Gamze Abakafee36392019-10-03 11:17:24 +0000441 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
442 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400443 TrafficQueues: TrafficQueues}); err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000444 log.Errorw("Failed to remove traffic queues", log.Fields{"error": err})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400445 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400446 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000447 log.Debug("Removed traffic queues successfully")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400448 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000449 IntfId: sq.intfID, OnuId: sq.onuID,
450 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400451 TrafficScheds: TrafficSched}); err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000452 log.Errorw("failed to remove traffic schedulers", log.Fields{"error": err})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400453 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400454 }
455
salmansiddiqui7ac62132019-08-22 03:58:50 +0000456 log.Debug("Removed traffic schedulers successfully")
457
458 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400459 * delete the meter id on the KV store.
460 */
Gamze Abakafee36392019-10-03 11:17:24 +0000461 err = f.resourceMgr.RemoveMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400462 if err != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000463 log.Errorf("Failed to remove meter for onu %d, meter id %d", sq.onuID, KVStoreMeter.MeterId)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000464 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400465 }
466 log.Debugw("Removed-meter-from-KV-store successfully", log.Fields{"MeterId": KVStoreMeter.MeterId, "dir": Direction})
467 return err
468}
469
Gamze Abakafee36392019-10-03 11:17:24 +0000470// This function allocates tconts and GEM ports for an ONU
471func (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) {
472 var allocIDs []uint32
473 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530474 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530475 tpInstanceExists := false
Gamze Abakafee36392019-10-03 11:17:24 +0000476
477 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(intfID, onuID, uniID)
478 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400479
480 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530481
482 log.Infow("creating-new-tcont-and-gem", log.Fields{"pon": intfID, "onu": onuID, "uni": uniID})
483
Manikkaraj kb1d51442019-07-23 10:41:02 -0400484 // Check tech profile instance already exists for derived port name
Girish Gowdra54934262019-11-13 14:19:55 +0530485 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000486 if techProfileInstance == nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530487 log.Infow("tp-instance-not-found--creating-new", log.Fields{"path": tpPath})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000488 techProfileInstance = f.techprofile[intfID].CreateTechProfInstance(TpID, uni, intfID)
489 if techProfileInstance == nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530490 // This should not happen, something wrong in KV backend transaction
491 log.Error("tp-instance-create-failed")
Gamze Abakafee36392019-10-03 11:17:24 +0000492 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530493 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000494 f.resourceMgr.UpdateTechProfileIDForOnu(intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530495 } else {
496 log.Debugw("Tech-profile-instance-already-exist-for-given port-name", log.Fields{"uni": uni})
Girish Gowdra3d633032019-12-10 16:37:05 +0530497 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530498 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400499 if UsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000500 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
501 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
502 if err := f.CreateSchedulerQueues(sq); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400503 log.Errorw("CreateSchedulerQueues Failed-upstream", log.Fields{"error": err, "meterID": UsMeterID})
Gamze Abakafee36392019-10-03 11:17:24 +0000504 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400505 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530506 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400507 if DsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000508 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
509 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
510 if err := f.CreateSchedulerQueues(sq); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400511 log.Errorw("CreateSchedulerQueues Failed-downstream", log.Fields{"error": err, "meterID": DsMeterID})
Gamze Abakafee36392019-10-03 11:17:24 +0000512 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400513 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530514 }
Gamze Abakafee36392019-10-03 11:17:24 +0000515
516 allocID := techProfileInstance.UsScheduler.AllocID
Gamze Abakafee36392019-10-03 11:17:24 +0000517 for _, gem := range techProfileInstance.UpstreamGemPortAttributeList {
Gamze Abakafee36392019-10-03 11:17:24 +0000518 gemPortIDs = append(gemPortIDs, gem.GemportID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400519 }
Gamze Abakafee36392019-10-03 11:17:24 +0000520
Girish Gowdra3d633032019-12-10 16:37:05 +0530521 if tpInstanceExists {
522 return allocID, gemPortIDs, techProfileInstance
523 }
524
525 allocIDs = appendUnique(allocIDs, allocID)
526 for _, gemPortID := range gemPortIDs {
527 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
528 }
529
Gamze Abakafee36392019-10-03 11:17:24 +0000530 log.Debugw("Allocated Tcont and GEM ports", log.Fields{"allocIDs": allocIDs, "gemports": allgemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530531 // Send Tconts and GEM ports to KV store
Gamze Abakafee36392019-10-03 11:17:24 +0000532 f.storeTcontsGEMPortsIntoKVStore(intfID, onuID, uniID, allocIDs, allgemPortIDs)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000533 return allocID, gemPortIDs, techProfileInstance
manikkaraj kbf256be2019-03-25 00:13:48 +0530534}
535
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700536func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530537
538 log.Debugw("Storing allocated Tconts and GEM ports into KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700539 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "allocID": allocID, "gemPortIDs": gemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530540 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700541 if err := f.resourceMgr.UpdateAllocIdsForOnu(intfID, onuID, uniID, allocID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530542 log.Error("Errow while uploading allocID to KV store")
543 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700544 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(intfID, onuID, uniID, gemPortIDs); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530545 log.Error("Errow while uploading GEMports to KV store")
546 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700547 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(gemPortIDs, intfID, onuID, uniID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530548 log.Error("Errow while uploading gemtopon map to KV store")
549 }
550 log.Debug("Stored tconts and GEM into KV store successfully")
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400551 for _, gemPort := range gemPortIDs {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700552 f.addGemPortToOnuInfoMap(intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400553 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530554}
555
556func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000557 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530558 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000559 for _, intfID := range techRange.IntfIds {
560 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400561 tpCount++
salmansiddiqui7ac62132019-08-22 03:58:50 +0000562 log.Debugw("Init tech profile done", log.Fields{"intfID": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530563 }
564 }
565 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400566 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530567 log.Errorw("Error while populating techprofile",
Manikkaraj kb1d51442019-07-23 10:41:02 -0400568 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000569 return errors.New("error while populating techprofile mgrs")
manikkaraj kbf256be2019-03-25 00:13:48 +0530570 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400571 log.Infow("Populated techprofile for ponports successfully",
572 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
manikkaraj kbf256be2019-03-25 00:13:48 +0530573 return nil
574}
575
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700576func (f *OpenOltFlowMgr) addUpstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530577 portNo uint32, uplinkClassifier map[string]interface{},
578 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700579 allocID uint32, gemportID uint32) {
580 uplinkClassifier[PacketTagType] = SingleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530581 log.Debugw("Adding upstream data flow", log.Fields{"uplinkClassifier": uplinkClassifier, "uplinkAction": uplinkAction})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700582 f.addHSIAFlow(intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700583 Upstream, logicalFlow, allocID, gemportID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530584 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530585}
586
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700587func (f *OpenOltFlowMgr) addDownstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530588 portNo uint32, downlinkClassifier map[string]interface{},
589 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700590 allocID uint32, gemportID uint32) {
591 downlinkClassifier[PacketTagType] = DoubleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530592 log.Debugw("Adding downstream data flow", log.Fields{"downlinkClassifier": downlinkClassifier,
593 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400594 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
595 if vlan, exists := downlinkClassifier[VlanVid]; exists {
596 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700597 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Manikkaraj kb1d51442019-07-23 10:41:02 -0400598 if uint32(metadata.(uint64)) == MkUniPortNum(intfID, onuID, uniID) {
599 log.Infow("Ignoring DL trap device flow from core", log.Fields{"flow": logicalFlow})
600 return
601 }
602 }
603 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530604 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400605
Manikkaraj k884c1242019-04-11 16:26:42 +0530606 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700607 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400608 // vlan_vid is a uint32. must be type asserted as such or conversion fails
609 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530610 if ok {
611 downlinkAction[VlanVid] = dlClVid & 0xfff
612 } else {
613 log.Error("dl-classifier-vid-type-conversion-failed")
614 return
615 }
616
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700617 f.addHSIAFlow(intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700618 Downstream, logicalFlow, allocID, gemportID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530619}
620
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700621func (f *OpenOltFlowMgr) addHSIAFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +0530622 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700623 allocID uint32, gemPortID uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530624 var networkIntfID uint32
Manikkaraj k884c1242019-04-11 16:26:42 +0530625 /* One of the OLT platform (Broadcom BAL) requires that symmetric
626 flows require the same flow_id to be used across UL and DL.
627 Since HSIA flow is the only symmetric flow currently, we need to
628 re-use the flow_id across both direction. The 'flow_category'
629 takes priority over flow_cookie to find any available HSIA_FLOW
630 id for the ONU.
631 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700632 log.Debugw("Adding HSIA flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "classifier": classifier,
633 "action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530634 "logicalFlow": *logicalFlow})
Gamze Abakafee36392019-10-03 11:17:24 +0000635 var vlanPbit uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400636 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000637 vlanPbit = classifier[VlanPcp].(uint32)
638 log.Debugw("Found pbit in the flow", log.Fields{"VlanPbit": vlanPbit})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400639 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700640 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Girish Gowdra3d633032019-12-10 16:37:05 +0530641 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
642 log.Debug("Flow-exists--not-re-adding")
643 return
644 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530645 flowID, err := f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530646 if err != nil {
647 log.Errorw("Flow id unavailable for HSIA flow", log.Fields{"direction": direction})
648 return
649 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700650 var classifierProto *openoltpb2.Classifier
651 var actionProto *openoltpb2.Action
Manikkaraj k884c1242019-04-11 16:26:42 +0530652 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
653 log.Error("Error in making classifier protobuf for hsia flow")
654 return
655 }
656 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
657 if actionProto = makeOpenOltActionField(action); actionProto == nil {
658 log.Errorw("Error in making action protobuf for hsia flow", log.Fields{"direction": direction})
659 return
660 }
661 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530662 networkIntfID, err = getNniIntfID(classifier, action)
663 if err != nil {
664 log.Error("Failed to get nniIntf ID")
665 return
666 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700667 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
668 OnuId: int32(onuID),
669 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000670 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530671 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700672 AllocId: int32(allocID),
673 NetworkIntfId: int32(networkIntfID),
674 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530675 Classifier: classifierProto,
676 Action: actionProto,
677 Priority: int32(logicalFlow.Priority),
678 Cookie: logicalFlow.Cookie,
679 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400680 if ok := f.addFlowToDevice(logicalFlow, &flow); ok {
Manikkaraj k884c1242019-04-11 16:26:42 +0530681 log.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530682 flowsToKVStore := f.getUpdatedFlowInfo(&flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
Manikkaraj k884c1242019-04-11 16:26:42 +0530683 if err := f.updateFlowInfoToKVStore(flow.AccessIntfId,
684 flow.OnuId,
685 flow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400686 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530687 log.Errorw("Error uploading HSIA flow into KV store", log.Fields{"flow": flow, "direction": direction, "error": err})
688 return
689 }
690 }
691}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700692func (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 +0530693
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700694 var dhcpFlow openoltpb2.Flow
695 var actionProto *openoltpb2.Action
696 var classifierProto *openoltpb2.Classifier
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530697 var flowID uint32
698 networkIntfID, err := getNniIntfID(classifier, action)
699 if err != nil {
700 log.Error("Failed to get nniIntf ID")
701 return
702 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530703
704 // Clear the action map
705 for k := range action {
706 delete(action, k)
707 }
708
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700709 action[TrapToHost] = true
710 classifier[UDPSrc] = uint32(68)
711 classifier[UDPDst] = uint32(67)
712 classifier[PacketTagType] = SingleTag
713 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530714
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700715 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Girish Gowdra3d633032019-12-10 16:37:05 +0530716 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
717 log.Debug("Flow-exists--not-re-adding")
718 return
719 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530720
Girish Gowdra3d633032019-12-10 16:37:05 +0530721 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 +0530722
723 if err != nil {
Girish Gowdra3d633032019-12-10 16:37:05 +0530724 log.Errorw("flowId unavailable for UL DHCP", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530725 return
726 }
727
728 log.Debugw("Creating UL DHCP flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID})
729
730 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
731 log.Error("Error in making classifier protobuf for ul flow")
732 return
733 }
734 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
735 if actionProto = makeOpenOltActionField(action); actionProto == nil {
736 log.Error("Error in making action protobuf for ul flow")
737 return
738 }
739
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700740 dhcpFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
741 OnuId: int32(onuID),
742 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530743 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700744 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700745 AllocId: int32(allocID),
746 NetworkIntfId: int32(networkIntfID),
747 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530748 Classifier: classifierProto,
749 Action: actionProto,
750 Priority: int32(logicalFlow.Priority),
751 Cookie: logicalFlow.Cookie,
752 PortNo: portNo}
753
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400754 if ok := f.addFlowToDevice(logicalFlow, &dhcpFlow); ok {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530755 log.Debug("DHCP UL flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530756 flowsToKVStore := f.getUpdatedFlowInfo(&dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530757 if err := f.updateFlowInfoToKVStore(dhcpFlow.AccessIntfId,
758 dhcpFlow.OnuId,
759 dhcpFlow.UniId,
760 dhcpFlow.FlowId, flowsToKVStore); err != nil {
761 log.Errorw("Error uploading DHCP UL flow into KV store", log.Fields{"flow": dhcpFlow, "error": err})
762 return
763 }
764 }
765
manikkaraj kbf256be2019-03-25 00:13:48 +0530766 return
767}
768
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700769// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530770func (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 -0700771 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 +0530772
773 uplinkClassifier := make(map[string]interface{})
774 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +0530775
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700776 var upstreamFlow openoltpb2.Flow
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530777 var networkIntfID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530778
779 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700780 uplinkClassifier[EthType] = uint32(EapEthType)
781 uplinkClassifier[PacketTagType] = SingleTag
782 uplinkClassifier[VlanVid] = vlanID
manikkaraj kbf256be2019-03-25 00:13:48 +0530783 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700784 uplinkAction[TrapToHost] = true
785 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
Girish Gowdra3d633032019-12-10 16:37:05 +0530786 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
787 log.Debug("Flow-exists--not-re-adding")
788 return
789 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530790 //Add Uplink EAPOL Flow
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530791 uplinkFlowID, err := f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530792 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700793 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manikkaraj k884c1242019-04-11 16:26:42 +0530794 return
manikkaraj kbf256be2019-03-25 00:13:48 +0530795 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700796 var classifierProto *openoltpb2.Classifier
797 var actionProto *openoltpb2.Action
798 log.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530799
800 if classifierProto = makeOpenOltClassifierField(uplinkClassifier); classifierProto == nil {
801 log.Error("Error in making classifier protobuf for ul flow")
802 return
803 }
804 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
805 if actionProto = makeOpenOltActionField(uplinkAction); actionProto == nil {
806 log.Error("Error in making action protobuf for ul flow")
807 return
808 }
809 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530810 networkIntfID, err = getNniIntfID(classifier, action)
811 if err != nil {
812 log.Error("Failed to get nniIntf ID")
813 return
814 }
815
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700816 upstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
817 OnuId: int32(onuID),
818 UniId: int32(uniID),
819 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700820 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700821 AllocId: int32(allocID),
822 NetworkIntfId: int32(networkIntfID),
823 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530824 Classifier: classifierProto,
825 Action: actionProto,
826 Priority: int32(logicalFlow.Priority),
827 Cookie: logicalFlow.Cookie,
828 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400829 if ok := f.addFlowToDevice(logicalFlow, &upstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530830 log.Debug("EAPOL UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400831 flowCategory := "EAPOL"
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530832 flowsToKVStore := f.getUpdatedFlowInfo(&upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
manikkaraj kbf256be2019-03-25 00:13:48 +0530833 if err := f.updateFlowInfoToKVStore(upstreamFlow.AccessIntfId,
834 upstreamFlow.OnuId,
835 upstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400836 upstreamFlow.FlowId,
837 /* lowCategory, */
838 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530839 log.Errorw("Error uploading EAPOL UL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
840 return
841 }
842 }
Girish Gowdra3d633032019-12-10 16:37:05 +0530843
manikkaraj kbf256be2019-03-25 00:13:48 +0530844 log.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
845}
846
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700847func makeOpenOltClassifierField(classifierInfo map[string]interface{}) *openoltpb2.Classifier {
848 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -0700849
850 classifier.EthType, _ = classifierInfo[EthType].(uint32)
851 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
852 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
853 vid := vlanID & VlanvIDMask
854 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -0400855 classifier.OVid = vid
856 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530857 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700858 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
859 vid := uint32(metadata)
860 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -0400861 classifier.IVid = vid
862 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530863 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700864 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400865 if vlanPcp == 0 {
866 classifier.OPbits = VlanPCPMask
867 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700868 classifier.OPbits = vlanPcp & VlanPCPMask
Manikkaraj kb1d51442019-07-23 10:41:02 -0400869 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530870 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700871 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
872 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
873 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
874 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
875 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
876 classifier.PktTagType = pktTagType
877
878 switch pktTagType {
879 case SingleTag:
880 case DoubleTag:
881 case Untagged:
882 default:
manikkaraj kbf256be2019-03-25 00:13:48 +0530883 log.Error("Invalid tag type in classifier") // should not hit
884 return nil
885 }
886 }
887 return &classifier
888}
889
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700890func makeOpenOltActionField(actionInfo map[string]interface{}) *openoltpb2.Action {
891 var actionCmd openoltpb2.ActionCmd
892 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +0530893 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700894 if _, ok := actionInfo[PopVlan]; ok {
895 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530896 action.Cmd.RemoveOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700897 } else if _, ok := actionInfo[PushVlan]; ok {
898 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530899 action.Cmd.AddOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700900 } else if _, ok := actionInfo[TrapToHost]; ok {
901 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +0530902 } else {
903 log.Errorw("Invalid-action-field", log.Fields{"action": actionInfo})
904 return nil
905 }
906 return &action
907}
908
Manikkaraj kb1d51442019-07-23 10:41:02 -0400909func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uni string, TpID uint32) string {
910 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530911}
912
Gamze Abakafee36392019-10-03 11:17:24 +0000913// DeleteTechProfileInstances removes the tech profile instances from persistent storage
914func (f *OpenOltFlowMgr) DeleteTechProfileInstances(intfID uint32, onuID uint32, uniID uint32, sn string) error {
915 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(intfID, onuID, uniID)
Devmalya Paul495b94a2019-08-27 19:42:00 -0400916 uniPortName := fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +0000917 for _, tpID := range tpIDList {
918 if err := f.DeleteTechProfileInstance(intfID, onuID, uniID, uniPortName, tpID); err != nil {
919 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 +0530920 // return err
921 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +0000922 }
923 }
924 return nil
925}
926
927// DeleteTechProfileInstance removes the tech profile instance from persistent storage
928func (f *OpenOltFlowMgr) DeleteTechProfileInstance(intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
929 if uniPortName == "" {
930 uniPortName = fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
931 }
Devmalya Paul495b94a2019-08-27 19:42:00 -0400932 if err := f.techprofile[intfID].DeleteTechProfileInstance(tpID, uniPortName); err != nil {
933 log.Debugw("Failed-to-delete-tp-instance-from-kv-store", log.Fields{"tp-id": tpID, "uni-port-name": uniPortName})
934 return err
935 }
936 return nil
937}
938
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700939func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530940 if len(classifier) == 0 { // should never happen
941 log.Error("Invalid classfier object")
942 return 0
943 }
Girish Gowdra3d633032019-12-10 16:37:05 +0530944 log.Debugw("generating flow store cookie", log.Fields{"classifier": classifier, "gemPortID": gemPortID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530945 var jsonData []byte
946 var flowString string
947 var err error
948 // TODO: Do we need to marshall ??
949 if jsonData, err = json.Marshal(classifier); err != nil {
950 log.Error("Failed to encode classifier")
951 return 0
952 }
953 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700954 if gemPortID != 0 {
955 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +0530956 }
957 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700958 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +0530959 hash := big.NewInt(0)
960 hash.SetBytes(h.Sum(nil))
Girish Gowdra3d633032019-12-10 16:37:05 +0530961 generatedHash := hash.Uint64()
962 log.Debugw("hash generated", log.Fields{"hash": generatedHash})
963 return generatedHash
manikkaraj kbf256be2019-03-25 00:13:48 +0530964}
965
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530966func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openoltpb2.Flow, flowStoreCookie uint64, flowCategory string, deviceFlowID uint32, logicalFlowID uint64) *[]rsrcMgr.FlowInfo {
967 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700968 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400969 /* For flows which trap out of the NNI, the AccessIntfId is invalid
970 (set to -1). In such cases, we need to refer to the NetworkIntfId .
971 */
972 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700973 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400974 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700975 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400976 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700977 // Get existing flows matching flowid for given subscriber from KV store
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530978 existingFlows := f.resourceMgr.GetFlowIDInfo(intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -0400979 if existingFlows != nil {
980 log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700981 //for _, f := range *existingFlows {
982 // flows = append(flows, f)
983 //}
984 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -0400985 }
986 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 +0530987 return &flows
988}
989
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400990//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
991// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
992// var intfId uint32
993// /* For flows which trap out of the NNI, the AccessIntfId is invalid
994// (set to -1). In such cases, we need to refer to the NetworkIntfId .
995// */
996// if flow.AccessIntfId != -1 {
997// intfId = uint32(flow.AccessIntfId)
998// } else {
999// intfId = uint32(flow.NetworkIntfId)
1000// }
1001// // Get existing flows matching flowid for given subscriber from KV store
1002// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
1003// if existingFlows != nil {
1004// log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
1005// for _, f := range *existingFlows {
1006// flows = append(flows, f)
1007// }
1008// }
1009// log.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
1010// return &flows
1011//}
1012
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001013func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
manikkaraj k17652a72019-05-06 09:06:36 -04001014 log.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001015 if err := f.resourceMgr.UpdateFlowIDInfo(intfID, onuID, uniID, flowID, flows); err != nil {
manikkaraj k17652a72019-05-06 09:06:36 -04001016 log.Debug("Error while Storing flow into KV store")
1017 return err
1018 }
1019 log.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +05301020 return nil
1021}
1022
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001023func (f *OpenOltFlowMgr) addFlowToDevice(logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) bool {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001024
1025 var intfID uint32
1026 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1027 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1028 */
1029 if deviceFlow.AccessIntfId != -1 {
1030 intfID = uint32(deviceFlow.AccessIntfId)
1031 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001032 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001033 intfID = uint32(deviceFlow.NetworkIntfId)
1034 }
1035
manikkaraj kbf256be2019-03-25 00:13:48 +05301036 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1037 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001038
1039 st, _ := status.FromError(err)
1040 if st.Code() == codes.AlreadyExists {
Gamze Abakafee36392019-10-03 11:17:24 +00001041 log.Debug("Flow already exists", log.Fields{"err": err, "deviceFlow": deviceFlow})
Girish Gowdra3d633032019-12-10 16:37:05 +05301042 return true
manikkaraj kbf256be2019-03-25 00:13:48 +05301043 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001044
1045 if err != nil {
1046 log.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": deviceFlow})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001047 f.resourceMgr.FreeFlowID(intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001048 return false
1049 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001050 f.registerFlow(logicalFlow, deviceFlow)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301051 log.Debugw("Flow added to device successfully ", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001052 return true
1053}
1054
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001055func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) bool {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001056 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1057 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1058 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001059 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
1060 log.Warnw("Can not remove flow from device since it's unreachable", log.Fields{"err": err, "deviceFlow": deviceFlow})
1061 //Assume the flow is removed
1062 return true
1063 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001064 log.Errorw("Failed to Remove flow from device", log.Fields{"err": err, "deviceFlow": deviceFlow})
1065 return false
serkant.uluderya245caba2019-09-24 23:15:29 -07001066
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001067 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001068 log.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301069 return true
1070}
1071
1072/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1073 //update core flows_proxy : flows_proxy.update('/', flows)
1074}
1075
1076func generateStoredId(flowId uint32, direction string)uint32{
1077
David K. Bainbridge82efc492019-09-04 09:57:11 -07001078 if direction == Upstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301079 log.Debug("Upstream flow shifting flowid")
1080 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001081 }else if direction == Downstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301082 log.Debug("Downstream flow not shifting flowid")
1083 return flowId
1084 }else{
1085 log.Errorw("Unrecognized direction",log.Fields{"direction": direction})
1086 return flowId
1087 }
1088}
1089
1090*/
1091
Humera Kouser94d7a842019-08-25 19:04:32 -04001092func (f *OpenOltFlowMgr) addLLDPFlow(flow *ofp.OfpFlowStats, portNo uint32) {
1093
1094 classifierInfo := make(map[string]interface{})
1095 actionInfo := make(map[string]interface{})
1096
1097 classifierInfo[EthType] = uint32(LldpEthType)
1098 classifierInfo[PacketTagType] = Untagged
1099 actionInfo[TrapToHost] = true
1100
1101 // LLDP flow is installed to trap LLDP packets on the NNI port.
1102 // We manage flow_id resource pool on per PON port basis.
1103 // Since this situation is tricky, as a hack, we pass the NNI port
1104 // index (network_intf_id) as PON port Index for the flow_id resource
1105 // pool. Also, there is no ONU Id available for trapping LLDP packets
1106 // on NNI port, use onu_id as -1 (invalid)
1107 // ****************** CAVEAT *******************
1108 // This logic works if the NNI Port Id falls within the same valid
1109 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1110 // we need to have a re-look at this.
1111 // *********************************************
1112
1113 var onuID = -1
1114 var uniID = -1
1115 var gemPortID = -1
1116
1117 var networkInterfaceID = IntfIDFromNniPortNum(portNo)
1118 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301119 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Humera Kouser94d7a842019-08-25 19:04:32 -04001120 log.Debug("Flow-exists--not-re-adding")
1121 return
1122 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301123 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001124
1125 if err != nil {
1126 log.Errorw("Flow id unavailable for LLDP traponNNI flow", log.Fields{"error": err})
1127 return
1128 }
1129 var classifierProto *openoltpb2.Classifier
1130 var actionProto *openoltpb2.Action
1131 if classifierProto = makeOpenOltClassifierField(classifierInfo); classifierProto == nil {
1132 log.Error("Error in making classifier protobuf for LLDP trap on nni flow")
1133 return
1134 }
1135 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1136 if actionProto = makeOpenOltActionField(actionInfo); actionProto == nil {
1137 log.Error("Error in making action protobuf for LLDP trap on nni flow")
1138 return
1139 }
1140 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
1141
1142 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1143 OnuId: int32(onuID), // OnuId not required
1144 UniId: int32(uniID), // UniId not used
1145 FlowId: flowID,
1146 FlowType: Downstream,
1147 NetworkIntfId: int32(networkInterfaceID),
1148 GemportId: int32(gemPortID),
1149 Classifier: classifierProto,
1150 Action: actionProto,
1151 Priority: int32(flow.Priority),
1152 Cookie: flow.Cookie,
1153 PortNo: portNo}
1154 if ok := f.addFlowToDevice(flow, &downstreamflow); ok {
1155 log.Debug("LLDP trap on NNI flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301156 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID, flow.Id)
Humera Kouser94d7a842019-08-25 19:04:32 -04001157 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1158 int32(onuID),
1159 int32(uniID),
1160 flowID, flowsToKVStore); err != nil {
1161 log.Errorw("Error uploading LLDP flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1162 }
1163 }
1164 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301165}
1166
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301167func getUniPortPath(intfID uint32, onuID int32, uniID int32) string {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001168 return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1169}
1170
1171//getOnuChildDevice to fetch onu
1172func (f *OpenOltFlowMgr) getOnuChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
1173 log.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
1174 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
1175 onuDevice := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301176 if onuDevice == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001177 log.Errorw("onu not found", log.Fields{"intfId": parentPortNo, "onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301178 return nil, errors.New("onu not found")
manikkaraj kbf256be2019-03-25 00:13:48 +05301179 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301180 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1181 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301182}
1183
1184func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001185 log.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301186 return nil
1187}
1188
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001189func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
1190 log.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301191}
1192
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001193func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001194 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001195 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001196 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001197 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001198}
1199
Girish Gowdra6b130582019-11-20 16:45:20 +05301200func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1201 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
1202 if err != nil {
1203 log.Errorw("error fetching child device from core", log.Fields{"onuId": onuID})
1204 return err
1205 }
1206
1207 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
1208 log.Debugw("sending gem port delete to openonu adapter", log.Fields{"msg": *delGemPortMsg})
1209 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1210 delGemPortMsg,
1211 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
1212 f.deviceHandler.deviceType,
1213 onuDevice.Type,
1214 onuDevice.Id,
1215 onuDevice.ProxyAddress.DeviceId, ""); sendErr != nil {
1216 log.Errorw("failure sending del gem port to onu adapter", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1217 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1218 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1219 return sendErr
1220 }
1221 log.Debugw("success sending del gem port to onu adapter", log.Fields{"msg": delGemPortMsg})
1222 return nil
1223}
1224
1225func (f *OpenOltFlowMgr) sendDeleteTcontToChild(intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1226 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
1227 if err != nil {
1228 log.Errorw("error fetching child device from core", log.Fields{"onuId": onuID})
1229 return err
1230 }
1231
1232 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
1233 log.Debugw("sending tcont delete to openonu adapter", log.Fields{"msg": *delTcontMsg})
1234 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1235 delTcontMsg,
1236 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
1237 f.deviceHandler.deviceType,
1238 onuDevice.Type,
1239 onuDevice.Id,
1240 onuDevice.ProxyAddress.DeviceId, ""); sendErr != nil {
1241 log.Errorw("failure sending del tcont to onu adapter", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1242 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1243 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1244 return sendErr
1245 }
1246 log.Debugw("success sending del tcont to onu adapter", log.Fields{"msg": delTcontMsg})
1247 return nil
1248}
1249
Girish Gowdra3d633032019-12-10 16:37:05 +05301250func (f *OpenOltFlowMgr) deletePendingFlows(Intf uint32, onuID int32, uniID int32) {
1251 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1252 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); ok {
1253 if val.(int) > 0 {
1254 pnFlDels := val.(int) - 1
1255 if pnFlDels > 0 {
1256 log.Debugw("flow delete succeeded, more pending",
1257 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID, "currPendingFlowCnt": pnFlDels})
1258 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1259 } else {
1260 log.Debugw("all pending flow deletes handled, removing entry from map",
1261 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1262 f.pendingFlowDelete.Delete(pnFlDelKey)
1263 }
1264 }
1265 } else {
1266 log.Debugw("no pending delete flows found",
1267 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1268
1269 }
1270
1271}
1272
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301273//clearResources clears pon resources in kv store and the device
1274func (f *OpenOltFlowMgr) clearResources(flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
1275 gemPortID int32, flowID uint32, flowDirection string,
1276 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001277
Chaitrashree G S90a17952019-11-14 21:51:21 -05001278 tpID, err := getTpIDFromFlow(flow)
1279 if err != nil {
1280 log.Error("metadata-is-not-present-invalid-flow-to-process", log.Fields{"pon": Intf, "onuID": onuID, "uniID": uniID})
1281 return err
1282 }
Gamze Abakafee36392019-10-03 11:17:24 +00001283
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001284 if len(updatedFlows) >= 0 {
1285 // There are still flows referencing the same flow_id.
1286 // So the flow should not be freed yet.
1287 // For ex: Case of HSIA where same flow is shared
1288 // between DS and US.
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301289 f.updateFlowInfoToKVStore(int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001290 if len(updatedFlows) == 0 {
Girish Gowdra3d633032019-12-10 16:37:05 +05301291 // Do this for subscriber flows only (not trap from NNI flows)
1292 if onuID != -1 && uniID != -1 {
1293 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1294 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
1295 log.Debugw("creating entry for pending flow delete",
1296 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1297 f.pendingFlowDelete.Store(pnFlDelKey, 1)
1298 } else {
1299 pnFlDels := val.(int) + 1
1300 log.Debugw("updating flow delete entry",
1301 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID, "currPendingFlowCnt": pnFlDels})
1302 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1303 }
1304
1305 defer f.deletePendingFlows(Intf, onuID, uniID)
1306 }
1307
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301308 log.Debugw("Releasing flow Id to resource manager", log.Fields{"Intf": Intf, "onuId": onuID, "uniId": uniID, "flowId": flowID})
1309 f.resourceMgr.FreeFlowID(Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001310
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301311 uni := getUniPortPath(Intf, onuID, uniID)
1312 tpPath := f.getTPpath(Intf, uni, tpID)
Gamze Abakafee36392019-10-03 11:17:24 +00001313 log.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301314 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(tpID, tpPath)
Gamze Abakafee36392019-10-03 11:17:24 +00001315 if err != nil { // This should not happen, something wrong in KV backend transaction
1316 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": 20, "path": tpPath})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301317 return err
Gamze Abakafee36392019-10-03 11:17:24 +00001318 }
1319 if techprofileInst == nil {
1320 log.Errorw("Tech-profile-instance-does-not-exist-in-KV Store", log.Fields{"tpPath": tpPath})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301321 return err
Gamze Abakafee36392019-10-03 11:17:24 +00001322 }
1323
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301324 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00001325 if f.isGemPortUsedByAnotherFlow(gemPK) {
1326 flowIDs := f.flowsUsedByGemPort[gemPK]
1327 for i, flowIDinMap := range flowIDs {
1328 if flowIDinMap == flowID {
1329 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301330 // everytime flowsUsedByGemPort cache is updated the same should be updated
1331 // in kv store by calling UpdateFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001332 f.flowsUsedByGemPort[gemPK] = flowIDs
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301333 f.resourceMgr.UpdateFlowIDsForGem(Intf, uint32(gemPortID), flowIDs)
Gamze Abakafee36392019-10-03 11:17:24 +00001334 break
1335 }
1336 }
1337 log.Debugw("Gem port id is still used by other flows", log.Fields{"gemPortID": gemPortID, "usedByFlows": flowIDs})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301338 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00001339 }
Gamze Abakafee36392019-10-03 11:17:24 +00001340 log.Debugf("Gem port id %d is not used by another flow - releasing the gem port", gemPortID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301341 f.resourceMgr.RemoveGemPortIDForOnu(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001342 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1343 // 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 +05301344 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(uint32(gemPortID), Intf)
Gamze Abakafee36392019-10-03 11:17:24 +00001345 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301346 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1347 // by calling DeleteFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001348 delete(f.flowsUsedByGemPort, gemPK)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301349 f.resourceMgr.DeleteFlowIDsForGem(Intf, uint32(gemPortID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301350 f.resourceMgr.FreeGemPortID(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001351 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05301352 // Delete the gem port on the ONU.
1353 if err := f.sendDeleteGemPortToChild(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
1354 log.Errorw("error processing delete gem-port towards onu",
1355 log.Fields{"err": err, "pon": Intf, "onuID": onuID, "uniID": uniID, "gemPortId": gemPortID})
1356 }
Gamze Abakafee36392019-10-03 11:17:24 +00001357
Girish Gowdra54934262019-11-13 14:19:55 +05301358 ok, _ := f.isTechProfileUsedByAnotherGem(Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001359 if !ok {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301360 f.resourceMgr.RemoveTechProfileIDForOnu(Intf, uint32(onuID), uint32(uniID), tpID)
1361 f.RemoveSchedulerQueues(schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1362 f.RemoveSchedulerQueues(schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1363 f.DeleteTechProfileInstance(Intf, uint32(onuID), uint32(uniID), "", tpID)
1364 f.resourceMgr.FreeAllocID(Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301365 // Delete the TCONT on the ONU.
1366 if err := f.sendDeleteTcontToChild(Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
1367 log.Errorw("error processing delete tcont towards onu",
1368 log.Fields{"pon": Intf, "onuID": onuID, "uniID": uniID, "allocId": techprofileInst.UsScheduler.AllocID})
1369 }
Gamze Abakafee36392019-10-03 11:17:24 +00001370 }
1371 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001372 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301373 return nil
1374}
1375
1376func (f *OpenOltFlowMgr) clearFlowFromResourceManager(flow *ofp.OfpFlowStats, flowDirection string) {
1377
1378 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowDirection": flowDirection, "flow": *flow})
1379 var updatedFlows []rsrcMgr.FlowInfo
1380 var flowID uint32
1381 var onuID, uniID int32
1382 classifierInfo := make(map[string]interface{})
1383
1384 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
1385 if err != nil {
1386 log.Error(err)
1387 return
1388 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301389
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301390 onuID = int32(onu)
1391 uniID = int32(uni)
1392
1393 for _, field := range flows.GetOfbFields(flow) {
1394 if field.Type == flows.IP_PROTO {
1395 classifierInfo[IPProto] = field.GetIpProto()
1396 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
1397 }
1398 }
1399 log.Debugw("Extracted access info from flow to be deleted",
1400 log.Fields{"ponIntf": Intf, "onuID": onuID, "uniID": uniID})
1401
1402 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1403 onuID = -1
1404 uniID = -1
1405 log.Debug("Trap on nni flow set oni, uni to -1")
1406 Intf = IntfIDFromNniPortNum(inPort)
1407 }
1408 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(Intf, onuID, uniID)
1409 for _, flowID = range flowIds {
1410 flowInfo := f.resourceMgr.GetFlowIDInfo(Intf, onuID, uniID, flowID)
1411 if flowInfo == nil {
1412 log.Debugw("No FlowInfo found found in KV store",
1413 log.Fields{"Intf": Intf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1414 return
1415 }
1416 updatedFlows = nil
1417 for _, flow := range *flowInfo {
1418 updatedFlows = append(updatedFlows, flow)
1419 }
1420
1421 for i, storedFlow := range updatedFlows {
1422 if flow.Id == storedFlow.LogicalFlowID {
1423 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
1424 log.Debugw("Flow to be deleted", log.Fields{"flow": storedFlow})
1425 if ok := f.removeFlowFromDevice(&removeFlowMessage); ok {
1426 log.Debug("Flow removed from device successfully")
1427 //Remove the Flow from FlowInfo
1428 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1429 err = f.clearResources(flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
1430 flowID, flowDirection, portNum, updatedFlows)
1431 if err != nil {
1432 log.Error("Failed to clear resources for flow", log.Fields{"flow": storedFlow})
1433 return
1434 }
1435 } else {
1436 log.Error("Failed to remove flow from device")
1437 return
1438 }
1439 }
1440 }
1441 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001442}
1443
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001444//RemoveFlow removes the flow from the device
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001445func (f *OpenOltFlowMgr) RemoveFlow(flow *ofp.OfpFlowStats) {
1446 log.Debugw("Removing Flow", log.Fields{"flow": flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301447 var direction string
1448 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001449
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301450 for _, action := range flows.GetActions(flow) {
1451 if action.Type == flows.OUTPUT {
1452 if out := action.GetOutput(); out != nil {
1453 actionInfo[Output] = out.GetPort()
1454 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
1455 } else {
1456 log.Error("Invalid output port in action")
1457 return
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001458 }
1459 }
1460 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301461 if IsUpstream(actionInfo[Output].(uint32)) {
1462 direction = Upstream
1463 } else {
1464 direction = Downstream
1465 }
1466
1467 f.clearFlowFromResourceManager(flow, direction) //TODO: Take care of the limitations
1468
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001469 return
1470}
1471
Girish Gowdra3d633032019-12-10 16:37:05 +05301472func (f *OpenOltFlowMgr) waitForFlowDeletesToCompleteForOnu(ctx context.Context, intfID uint32, onuID uint32,
1473 uniID uint32, ch chan bool) {
1474 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
1475 for {
1476 select {
1477 case <-time.After(20 * time.Millisecond):
1478 if flowDelRefCnt, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok || flowDelRefCnt == 0 {
1479 log.Debug("pending flow deletes completed")
1480 ch <- true
1481 return
1482 }
1483 case <-ctx.Done():
1484 log.Error("flow delete wait handler routine canceled")
1485 return
1486 }
1487 }
1488}
1489
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001490// AddFlow add flow to device
Manikkaraj kb1d51442019-07-23 10:41:02 -04001491func (f *OpenOltFlowMgr) AddFlow(flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001492 classifierInfo := make(map[string]interface{})
1493 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001494 var UsMeterID uint32
1495 var DsMeterID uint32
1496
1497 log.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001498 formulateClassifierInfoFromFlow(classifierInfo, flow)
1499
1500 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
1501 if err != nil {
1502 // Error logging is already done in the called function
1503 // So just return in case of error
1504 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301505 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001506
manikkaraj k17652a72019-05-06 09:06:36 -04001507 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00001508 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
1509 if err != nil {
1510 // error if any, already logged in the called function
1511 return
manikkaraj k17652a72019-05-06 09:06:36 -04001512 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001513
David K. Bainbridge82efc492019-09-04 09:57:11 -07001514 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[Output]})
1515 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00001516
Humera Kouser94d7a842019-08-25 19:04:32 -04001517 if ethType, ok := classifierInfo[EthType]; ok {
1518 if ethType.(uint32) == LldpEthType {
1519 log.Info("Adding LLDP flow")
1520 f.addLLDPFlow(flow, portNo)
1521 return
1522 }
1523 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001524 if ipProto, ok := classifierInfo[IPProto]; ok {
1525 if ipProto.(uint32) == IPProtoDhcp {
1526 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001527 if udpSrc.(uint32) == uint32(67) {
1528 log.Debug("trap-dhcp-from-nni-flow")
1529 f.addDHCPTrapFlowOnNNI(flow, classifierInfo, portNo)
1530 return
1531 }
1532 }
1533 }
1534 }
A R Karthick1f85b802019-10-11 05:06:05 +00001535
1536 f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301537 f.resourceMgr.AddUniPortToOnuInfo(intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00001538
Chaitrashree G S90a17952019-11-14 21:51:21 -05001539 TpID, err := getTpIDFromFlow(flow)
1540 if err != nil {
1541 log.Error("metadata-is-not-present-invalid-flow-to-process", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1542 return
1543 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001544 log.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001545 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07001546 UsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001547 log.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
1548 } else {
Scott Baker355d1742019-10-24 10:57:52 -07001549 DsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001550 log.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
1551
1552 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301553
1554 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
1555 if _, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
1556 log.Debugw("no pending flows found, going ahead with flow install", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1557 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
1558 } else {
1559 ctx := context.Background()
1560 ctx, cancel := context.WithCancel(ctx)
1561 defer cancel()
1562 pendingFlowDelComplete := make(chan bool)
1563 go f.waitForFlowDeletesToCompleteForOnu(ctx, intfID, onuID, uniID, pendingFlowDelComplete)
1564 select {
1565 case <-pendingFlowDelComplete:
1566 log.Debugw("all pending flow deletes completed", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1567 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
1568
1569 case <-time.After(10 * time.Second):
1570 log.Errorw("pending flow deletes not completed after timeout", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1571 }
1572 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001573}
1574
1575//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04001576func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001577
1578 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301579 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001580 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301581 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301582 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301583 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04001584
Manikkaraj kb1d51442019-07-23 10:41:02 -04001585 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001586 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
manikkaraj k17652a72019-05-06 09:06:36 -04001587 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
1588 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1589 tpDownloadMsg,
1590 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
1591 f.deviceHandler.deviceType,
1592 onuDevice.Type,
1593 onuDevice.Id,
1594 onuDevice.ProxyAddress.DeviceId, "")
1595 if sendErr != nil {
1596 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1597 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1598 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1599 return sendErr
1600 }
1601 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05301602 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301603}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001604
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301605//UpdateOnuInfo function adds onu info to cache and kvstore
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001606func (f *OpenOltFlowMgr) UpdateOnuInfo(intfID uint32, onuID uint32, serialNum string) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301607
1608 f.lockCache.Lock()
1609 defer f.lockCache.Unlock()
1610 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
1611 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
1612 if err := f.resourceMgr.AddOnuInfo(intfID, onu); err != nil {
1613 log.Errorw("failed to add onu info", log.Fields{"onu": onu})
1614 return
1615 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001616 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
1617}
1618
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301619//addGemPortToOnuInfoMap function adds GEMport to ONU map
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001620func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(intfID uint32, onuID uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301621 f.lockCache.Lock()
1622 defer f.lockCache.Unlock()
1623 onugem := f.onuGemInfo[intfID]
1624 // update the gem to the local cache as well as to kv strore
1625 for idx, onu := range onugem {
1626 if onu.OnuID == onuID {
1627 // check if gem already exists , else update the cache and kvstore
1628 for _, gem := range onu.GemPorts {
1629 if gem == gemPort {
1630 log.Debugw("Gem already in cache, no need to update cache and kv store",
1631 log.Fields{"gem": gemPort})
1632 return
1633 }
1634 }
1635 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
1636 f.onuGemInfo[intfID] = onugem
1637 }
1638 }
1639 err := f.resourceMgr.AddGemToOnuGemInfo(intfID, onuID, gemPort)
1640 if err != nil {
1641 log.Errorw("Failed to add gem to onu", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001642 return
1643 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001644}
1645
1646// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001647
1648//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
1649func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301650
1651 f.lockCache.Lock()
1652 defer f.lockCache.Unlock()
1653
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001654 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 +05301655 // get onuid from the onugem info cache
1656 onugem := f.onuGemInfo[intfID]
1657 for _, onu := range onugem {
1658 for _, gem := range onu.GemPorts {
1659 if gem == gemPortID {
1660 return onu.OnuID, nil
1661 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001662 }
1663 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001664 log.Errorw("onuid is not found", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPort": gemPortID})
1665 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 -04001666}
1667
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001668//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
1669func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001670 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001671 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001672 var err error
1673
1674 if packetIn.IntfType == "pon" {
1675 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001676 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001677 log.Errorw("Unable to get ONU ID from GEM/PON port", log.Fields{"pon port": packetIn.IntfId, "gemport": packetIn.GemportId})
1678 return logicalPortNum, err
1679 }
1680 if packetIn.PortNo != 0 {
1681 logicalPortNum = packetIn.PortNo
1682 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001683 uniID := uint32(0) // FIXME - multi-uni support
1684 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001685 }
1686 // 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 +05301687 f.UpdateGemPortForPktIn(packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001688 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001689 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001690 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001691 log.Debugw("Retrieved logicalport from packet-in", log.Fields{
1692 "logicalPortNum": logicalPortNum,
1693 "IntfType": packetIn.IntfType,
1694 "packet": hex.EncodeToString(packetIn.Pkt),
1695 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001696 return logicalPortNum, nil
1697}
1698
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001699//GetPacketOutGemPortID returns gemPortId
1700func (f *OpenOltFlowMgr) GetPacketOutGemPortID(intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
1701 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001702 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301703
1704 f.lockCache.Lock()
1705 defer f.lockCache.Unlock()
1706 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum}
1707
1708 gemPortID, ok := f.packetInGemPort[pktInkey]
1709 if ok {
1710 log.Debugw("Found gemport for pktin key", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1711 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001712 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301713 //If gem is not found in cache try to get it from kv store, if found in kv store, update the cache and return.
1714 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(intfID, onuID, portNum)
1715 if err == nil {
1716 if gemPortID != 0 {
1717 f.packetInGemPort[pktInkey] = gemPortID
1718 log.Debugw("Found gem port from kv store and updating cache with gemport",
1719 log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1720 return gemPortID, nil
1721 }
1722 }
1723 log.Errorw("Failed to get gemport", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1724 return uint32(0), err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001725}
1726
Manikkaraj kb1d51442019-07-23 10:41:02 -04001727func installFlowOnAllGemports(
1728 f1 func(intfId uint32, onuId uint32, uniId uint32,
1729 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
1730 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32),
1731 f2 func(intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301732 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
1733 classifier map[string]interface{}, action map[string]interface{}),
Manikkaraj kb1d51442019-07-23 10:41:02 -04001734 args map[string]uint32,
1735 classifier map[string]interface{}, action map[string]interface{},
1736 logicalFlow *ofp.OfpFlowStats,
1737 gemPorts []uint32,
1738 FlowType string,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001739 vlanID ...uint32) {
1740 log.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
1741 for _, gemPortID := range gemPorts {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001742 if FlowType == HsiaFlow || FlowType == DhcpFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001743 f1(args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001744 } else if FlowType == EapolFlow {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301745 f2(args["intfId"], args["onuId"], args["uniId"], args["portNo"], logicalFlow, args["allocId"], gemPortID, vlanID[0], classifier, action)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001746 } else {
1747 log.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
1748 return
1749 }
1750 }
1751}
1752
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001753func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
1754 log.Debug("Adding trap-dhcp-of-nni-flow")
1755 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001756 classifier[PacketTagType] = DoubleTag
1757 action[TrapToHost] = true
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301758 var err error
1759 var networkInterfaceID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001760 /* We manage flowId resource pool on per PON port basis.
1761 Since this situation is tricky, as a hack, we pass the NNI port
1762 index (network_intf_id) as PON port Index for the flowId resource
1763 pool. Also, there is no ONU Id available for trapping DHCP packets
1764 on NNI port, use onu_id as -1 (invalid)
1765 ****************** CAVEAT *******************
1766 This logic works if the NNI Port Id falls within the same valid
1767 range of PON Port Ids. If this doesn't work for some OLT Vendor
1768 we need to have a re-look at this.
1769 *********************************************
1770 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001771 onuID := -1
1772 uniID := -1
1773 gemPortID := -1
1774 allocID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301775 networkInterfaceID, err = getNniIntfID(classifier, action)
1776 if err != nil {
1777 log.Error("Failed to get nniIntf ID")
1778 return
1779 }
1780
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001781 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301782 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001783 log.Debug("Flow-exists--not-re-adding")
1784 return
1785 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301786 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001787 if err != nil {
1788 log.Errorw("Flow id unavailable for DHCP traponNNI flow", log.Fields{"error": err})
1789 return
1790 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001791 var classifierProto *openoltpb2.Classifier
1792 var actionProto *openoltpb2.Action
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001793 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
1794 log.Error("Error in making classifier protobuf for dhcp trap on nni flow")
1795 return
1796 }
1797 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1798 if actionProto = makeOpenOltActionField(action); actionProto == nil {
1799 log.Error("Error in making action protobuf for dhcp trap on nni flow")
1800 return
1801 }
1802 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001803 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1804 OnuId: int32(onuID), // OnuId not required
1805 UniId: int32(uniID), // UniId not used
1806 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001807 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001808 AllocId: int32(allocID), // AllocId not used
1809 NetworkIntfId: int32(networkInterfaceID),
1810 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001811 Classifier: classifierProto,
1812 Action: actionProto,
1813 Priority: int32(logicalFlow.Priority),
1814 Cookie: logicalFlow.Cookie,
1815 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001816 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001817 log.Debug("DHCP trap on NNI flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301818 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001819 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1820 int32(onuID),
1821 int32(uniID),
1822 flowID, flowsToKVStore); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001823 log.Errorw("Error uploading DHCP DL flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1824 }
1825 }
1826 return
1827}
salmansiddiqui7ac62132019-08-22 03:58:50 +00001828
1829func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
1830 if MeterID == 0 { // This should never happen
1831 log.Error("Invalid meter id")
1832 return "", errors.New("invalid meter id")
1833 }
1834 if Dir == tp_pb.Direction_UPSTREAM {
1835 return "upstream", nil
1836 } else if Dir == tp_pb.Direction_DOWNSTREAM {
1837 return "downstream", nil
1838 }
1839 return "", nil
1840}
1841
1842func (f *OpenOltFlowMgr) checkAndAddFlow(args map[string]uint32, classifierInfo map[string]interface{},
Gamze Abakafee36392019-10-03 11:17:24 +00001843 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst *tp.TechProfile, gemPorts []uint32,
1844 TpID uint32, uni string) {
1845 var gemPort uint32
1846 intfID := args[IntfID]
1847 onuID := args[OnuID]
1848 uniID := args[UniID]
1849 portNo := args[PortNo]
1850 allocID := TpInst.UsScheduler.AllocID
salmansiddiqui7ac62132019-08-22 03:58:50 +00001851 if ipProto, ok := classifierInfo[IPProto]; ok {
1852 if ipProto.(uint32) == IPProtoDhcp {
1853 log.Info("Adding DHCP flow")
1854 if pcp, ok := classifierInfo[VlanPcp]; ok {
1855 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1856 tp_pb.Direction_UPSTREAM,
1857 pcp.(uint32))
1858 //Adding DHCP upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001859 f.addDHCPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001860 } else {
1861 //Adding DHCP upstream flow to all gemports
1862 installFlowOnAllGemports(f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, DhcpFlow)
1863 }
1864
1865 } else if ipProto == IgmpProto {
1866 log.Info("igmp flow add ignored, not implemented yet")
1867 return
1868 } else {
1869 log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
1870 return
1871 }
1872 } else if ethType, ok := classifierInfo[EthType]; ok {
1873 if ethType.(uint32) == EapEthType {
1874 log.Info("Adding EAPOL flow")
1875 var vlanID uint32
1876 if val, ok := classifierInfo[VlanVid]; ok {
1877 vlanID = (val.(uint32)) & VlanvIDMask
1878 } else {
1879 vlanID = DefaultMgmtVlan
1880 }
1881 if pcp, ok := classifierInfo[VlanPcp]; ok {
1882 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1883 tp_pb.Direction_UPSTREAM,
1884 pcp.(uint32))
1885
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301886 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID, gemPort, vlanID, classifierInfo, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001887 } else {
1888 installFlowOnAllGemports(nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, EapolFlow, vlanID)
1889 }
1890 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001891 } else if _, ok := actionInfo[PushVlan]; ok {
1892 log.Info("Adding upstream data rule")
1893 if pcp, ok := classifierInfo[VlanPcp]; ok {
1894 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1895 tp_pb.Direction_UPSTREAM,
1896 pcp.(uint32))
1897 //Adding HSIA upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001898 f.addUpstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001899 } else {
1900 //Adding HSIA upstream flow to all gemports
1901 installFlowOnAllGemports(f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1902 }
1903 } else if _, ok := actionInfo[PopVlan]; ok {
1904 log.Info("Adding Downstream data rule")
1905 if pcp, ok := classifierInfo[VlanPcp]; ok {
1906 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05001907 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001908 pcp.(uint32))
1909 //Adding HSIA downstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001910 f.addDownstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001911 } else {
1912 //Adding HSIA downstream flow to all gemports
1913 installFlowOnAllGemports(f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1914 }
1915 } else {
1916 log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
1917 return
1918 }
1919 // Send Techprofile download event to child device in go routine as it takes time
1920 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, TpID)
1921}
1922
Gamze Abakafee36392019-10-03 11:17:24 +00001923func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
1924 flowIDList := f.flowsUsedByGemPort[gemPK]
1925 if len(flowIDList) > 1 {
1926 return true
1927 }
1928 return false
1929}
1930
Girish Gowdra54934262019-11-13 14:19:55 +05301931func (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 +00001932 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ponIntf, onuID, uniID)
1933 tpGemPorts := tpInst.UpstreamGemPortAttributeList
1934 for _, currentGemPort := range currentGemPorts {
1935 for _, tpGemPort := range tpGemPorts {
1936 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
1937 return true, currentGemPort
1938 }
1939 }
1940 }
Girish Gowdra54934262019-11-13 14:19:55 +05301941 if tpInst.InstanceCtrl.Onu == "single-instance" {
1942 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
1943 f.resourceMgr.RemoveTechProfileIDForOnu(ponIntf, uint32(onuID), uint32(uniID), tpID)
1944 f.DeleteTechProfileInstance(ponIntf, uint32(onuID), uint32(uniID), "", tpID)
1945
1946 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
1947 // still be used on other uni ports.
1948 // So, we need to check and make sure that no other gem port is referring to the given TP ID
1949 // on any other uni port.
1950 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(tpID, ponIntf, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301951 log.Debugw("got single instance tp instances", log.Fields{"tpInstances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05301952 for i := 0; i < len(tpInstances); i++ {
1953 tpI := tpInstances[i]
1954 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05301955 for _, tpGemPort := range tpGemPorts {
1956 if tpGemPort.GemportID != gemPortID {
1957 log.Debugw("single instance tp is in use by gem", log.Fields{"gemPort": tpGemPort.GemportID})
1958 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05301959 }
1960 }
1961 }
1962 }
Girish Gowdra6b130582019-11-20 16:45:20 +05301963 log.Debug("tech profile is not in use by any gem")
Gamze Abakafee36392019-10-03 11:17:24 +00001964 return false, 0
1965}
1966
salmansiddiqui7ac62132019-08-22 03:58:50 +00001967func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07001968 for _, field := range flows.GetOfbFields(flow) {
1969 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001970 classifierInfo[EthType] = field.GetEthType()
1971 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001972 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001973 classifierInfo[IPProto] = field.GetIpProto()
1974 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001975 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001976 classifierInfo[InPort] = field.GetPort()
1977 log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001978 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05301979 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
salmansiddiqui7ac62132019-08-22 03:58:50 +00001980 log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001981 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001982 classifierInfo[VlanPcp] = field.GetVlanPcp()
1983 log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001984 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001985 classifierInfo[UDPDst] = field.GetUdpDst()
1986 log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001987 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001988 classifierInfo[UDPSrc] = field.GetUdpSrc()
1989 log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001990 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001991 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
1992 log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001993 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001994 classifierInfo[Ipv4Src] = field.GetIpv4Src()
1995 log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001996 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001997 classifierInfo[Metadata] = field.GetTableMetadata()
1998 log.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07001999 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002000 classifierInfo[TunnelID] = field.GetTunnelId()
2001 log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
2002 } else {
2003 log.Errorw("Un supported field type", log.Fields{"type": field.Type})
2004 return
2005 }
2006 }
2007}
2008
2009func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07002010 for _, action := range flows.GetActions(flow) {
2011 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002012 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002013 actionInfo[Output] = out.GetPort()
2014 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002015 } else {
2016 log.Error("Invalid output port in action")
2017 return errors.New("invalid output port in action")
2018 }
Scott Baker355d1742019-10-24 10:57:52 -07002019 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002020 actionInfo[PopVlan] = true
2021 log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002022 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002023 if out := action.GetPush(); out != nil {
2024 if tpid := out.GetEthertype(); tpid != 0x8100 {
2025 log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
2026 } else {
2027 actionInfo[PushVlan] = true
2028 actionInfo[TPID] = tpid
2029 log.Debugw("action-type-push-vlan",
2030 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
2031 }
2032 }
Scott Baker355d1742019-10-24 10:57:52 -07002033 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002034 if out := action.GetSetField(); out != nil {
2035 if field := out.GetField(); field != nil {
2036 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
2037 log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
2038 return errors.New("invalid openflow class")
2039 }
2040 /*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
2041 if ofbField := field.GetOfbField(); ofbField != nil {
2042 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
2043 if vlan := ofbField.GetVlanVid(); vlan != 0 {
2044 actionInfo[VlanVid] = vlan & 0xfff
2045 log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
2046 } else {
2047 log.Error("No Invalid vlan id in set vlan-vid action")
2048 }
2049 } else {
2050 log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
2051 }
2052 }
2053 }
2054 }
2055 } else {
2056 log.Errorw("Un supported action type", log.Fields{"type": action.Type})
2057 return errors.New("un supported action type")
2058 }
2059 }
2060 return nil
2061}
2062
2063func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002064 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002065 log.Debug("Controller bound trap flows, getting inport from tunnelid")
2066 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2067 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002068 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002069 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07002070 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 +00002071 } else {
2072 log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
2073 return errors.New("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
2074 }
2075 }
2076 } else {
2077 log.Debug("Non-Controller flows, getting uniport from tunnelid")
2078 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07002079 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002080 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002081 actionInfo[Output] = uniPort
2082 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 +00002083 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002084 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 +00002085 return errors.New("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid")
2086 }
2087 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2088 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002089 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002090 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07002091 log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[Output].(uint32),
2092 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002093 } else {
2094 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 -07002095 "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002096 return errors.New("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid")
2097 }
2098 }
2099 }
2100 return nil
2101}
Gamze Abakafee36392019-10-03 11:17:24 +00002102
Chaitrashree G S90a17952019-11-14 21:51:21 -05002103func getTpIDFromFlow(flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00002104 /* Metadata 8 bytes:
2105 Most Significant 2 Bytes = Inner VLAN
2106 Next 2 Bytes = Tech Profile ID(TPID)
2107 Least Significant 4 Bytes = Port ID
2108 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
2109 subscriber related flows.
2110 */
2111 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
2112 if metadata == 0 {
Chaitrashree G S90a17952019-11-14 21:51:21 -05002113 log.Error("metadata-is-not-present-in-flow-which-is-mandatory")
2114 return 0, errors.New("metadata-is-not-present-in-flow-which-is-mandatory")
Gamze Abakafee36392019-10-03 11:17:24 +00002115 }
2116 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002117 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00002118}
2119
2120func appendUnique(slice []uint32, item uint32) []uint32 {
2121 for _, sliceElement := range slice {
2122 if sliceElement == item {
2123 return slice
2124 }
2125 }
2126 return append(slice, item)
2127}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302128
2129// getNniIntfID gets nni intf id from the flow classifier/action
2130func getNniIntfID(classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
2131
2132 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
2133 if portType == voltha.Port_PON_OLT {
2134 intfID := IntfIDFromNniPortNum(action[Output].(uint32))
2135 log.Debugw("output Nni IntfID is", log.Fields{"intfid": intfID})
2136 return intfID, nil
2137 } else if portType == voltha.Port_ETHERNET_NNI {
2138 intfID := IntfIDFromNniPortNum(classifier[InPort].(uint32))
2139 log.Debugw("input Nni IntfID is", log.Fields{"intfid": intfID})
2140 return intfID, nil
2141 }
2142 return uint32(0), nil
2143}
2144
2145// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
2146func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32) {
2147 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort}
2148
2149 f.lockCache.Lock()
2150 defer f.lockCache.Unlock()
2151 _, ok := f.packetInGemPort[pktInkey]
2152 if ok {
2153 log.Debugw("pktin key found in cache , no need to update kv as we are assuming both will be in sync",
2154 log.Fields{"pktinkey": pktInkey, "gem": gemPort})
2155 } else {
2156 f.packetInGemPort[pktInkey] = gemPort
2157
2158 f.resourceMgr.UpdateGemPortForPktIn(pktInkey, gemPort)
2159 log.Debugw("pktin key not found in local cache updating cache and kv store", log.Fields{"pktinkey": pktInkey, "gem": gemPort})
2160 }
2161 return
2162}
2163
2164// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
2165func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(intfID uint32, onuID uint32, portNum uint32) {
2166
2167 f.lockCache.Lock()
2168 defer f.lockCache.Unlock()
2169 onugem := f.onuGemInfo[intfID]
2170 for idx, onu := range onugem {
2171 if onu.OnuID == onuID {
2172 for _, uni := range onu.UniPorts {
2173 if uni == portNum {
2174 log.Debugw("uni already in cache, no need to update cache and kv store",
2175 log.Fields{"uni": portNum})
2176 return
2177 }
2178 }
2179 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
2180 f.onuGemInfo[intfID] = onugem
2181 }
2182 }
2183 f.resourceMgr.AddUniPortToOnuInfo(intfID, onuID, portNum)
2184}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302185
2186func (f *OpenOltFlowMgr) loadFlowIDlistForGem(intf uint32) {
2187 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(intf)
2188 if err != nil {
2189 log.Error("Failed to get flowid list per gem", log.Fields{"intf": intf})
2190 return
2191 }
2192 for gem, FlowIDs := range flowIDsList {
2193 gemPK := gemPortKey{intf, uint32(gem)}
2194 f.flowsUsedByGemPort[gemPK] = FlowIDs
2195 }
2196 return
2197}