blob: fae77a98323ecaba06318ec8bf173af988eab42d [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"
23 "encoding/json"
24 "errors"
25 "fmt"
Manikkaraj kb1d51442019-07-23 10:41:02 -040026 "math/big"
27
manikkaraj kbf256be2019-03-25 00:13:48 +053028 "github.com/opencord/voltha-go/common/log"
29 tp "github.com/opencord/voltha-go/common/techprofile"
Matt Jeannereta93dbed2019-05-17 12:40:05 -040030 "github.com/opencord/voltha-go/rw_core/utils"
Manikkaraj k884c1242019-04-11 16:26:42 +053031 rsrcMgr "github.com/opencord/voltha-openolt-adapter/adaptercore/resourcemanager"
manikkaraj k17652a72019-05-06 09:06:36 -040032 ic "github.com/opencord/voltha-protos/go/inter_container"
manikkaraj kbf256be2019-03-25 00:13:48 +053033 ofp "github.com/opencord/voltha-protos/go/openflow_13"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070034 openoltpb2 "github.com/opencord/voltha-protos/go/openolt"
Manikkaraj kb1d51442019-07-23 10:41:02 -040035 tp_pb "github.com/opencord/voltha-protos/go/tech_profile"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070036 "github.com/opencord/voltha-protos/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040037
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -040038 //deepcopy "github.com/getlantern/deepcopy"
Daniele Rossi22db98e2019-07-11 11:50:00 +000039 "google.golang.org/grpc/codes"
40 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053041)
42
43const (
44 // Flow categories
manikkaraj kbf256be2019-03-25 00:13:48 +053045
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070046 //HsiaFlow flow category
47 HsiaFlow = "HSIA_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053048
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070049 //EapolFlow flow category
50 EapolFlow = "EAPOL_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053051
Manikkaraj kb1d51442019-07-23 10:41:02 -040052 //DhcpFlow flow category
53 DhcpFlow = "DHCP_FLOW"
54
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070055 //IPProtoDhcp flow category
56 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053057
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070058 //IPProtoIgmp flow category
59 IPProtoIgmp = 2
60
61 //EapEthType eapethtype value
62 EapEthType = 0x888e
63 //LldpEthType lldp ethtype value
64 LldpEthType = 0x88cc
65
66 //IgmpProto proto value
67 IgmpProto = 2
manikkaraj kbf256be2019-03-25 00:13:48 +053068
69 //FIXME - see also BRDCM_DEFAULT_VLAN in broadcom_onu.py
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070070
71 //DefaultMgmtVlan default vlan value
72 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053073
manikkaraj kbf256be2019-03-25 00:13:48 +053074 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070075
76 //UPSTREAM constant
77 UPSTREAM = "upstream"
78 //DOWNSTREAM constant
79 DOWNSTREAM = "downstream"
80 //PacketTagType constant
81 PacketTagType = "pkt_tag_type"
82 //UNTAGGED constant
83 UNTAGGED = "untagged"
84 //SingleTag constant
85 SingleTag = "single_tag"
86 //DoubleTag constant
87 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053088
89 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070090
91 //EthType constant
92 EthType = "eth_type"
93 //TPID constant
94 TPID = "tpid"
95 //IPProto constant
96 IPProto = "ip_proto"
97 //InPort constant
98 InPort = "in_port"
99 //VlanVid constant
100 VlanVid = "vlan_vid"
101 //VlanPcp constant
102 VlanPcp = "vlan_pcp"
103
104 //UDPDst constant
105 UDPDst = "udp_dst"
106 //UDPSrc constant
107 UDPSrc = "udp_src"
108 //Ipv4Dst constant
109 Ipv4Dst = "ipv4_dst"
110 //Ipv4Src constant
111 Ipv4Src = "ipv4_src"
112 //METADATA constant
113 METADATA = "metadata"
114 //TunnelID constant
115 TunnelID = "tunnel_id"
116 //OUTPUT constant
117 OUTPUT = "output"
118 // Actions
119
120 //PopVlan constant
121 PopVlan = "pop_vlan"
122 //PushVlan constant
123 PushVlan = "push_vlan"
124 //TrapToHost constant
125 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400126 //MaxMeterBand constant
127 MaxMeterBand = 2
128 //VlanPCPMask contant
129 VlanPCPMask = 0xFF
130 //VlanvIDMask constant
131 VlanvIDMask = 0xFFF
132 //MaxPonPorts constant
133 MaxPonPorts = 16
manikkaraj kbf256be2019-03-25 00:13:48 +0530134)
135
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400136type onuInfo struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700137 intfID uint32
138 onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400139 serialNumber string
140}
141
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700142type onuIDKey struct {
143 intfID uint32
144 onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400145}
146
147type gemPortKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700148 intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400149 gemPort uint32
150}
151
152type packetInInfoKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700153 intfID uint32
154 onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400155 logicalPort uint32
156}
157
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700158//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530159type OpenOltFlowMgr struct {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400160 techprofile []*tp.TechProfileMgr
161 deviceHandler *DeviceHandler
162 resourceMgr *rsrcMgr.OpenOltResourceMgr
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700163 onuIds map[onuIDKey]onuInfo //OnuId -> OnuInfo
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400164 onuSerialNumbers map[string]onuInfo //onu serial_number (string) -> OnuInfo
165 onuGemPortIds map[gemPortKey]onuInfo //GemPortId -> OnuInfo
166 packetInGemPort map[packetInInfoKey]uint32 //packet in gem port
167 storedDeviceFlows []ofp.OfpFlowStats /* Required during deletion to obtain device flows from logical flows */
manikkaraj kbf256be2019-03-25 00:13:48 +0530168}
169
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700170//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
manikkaraj kbf256be2019-03-25 00:13:48 +0530171func NewFlowManager(dh *DeviceHandler, rsrcMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
172 log.Info("Initializing flow manager")
173 var flowMgr OpenOltFlowMgr
174 flowMgr.deviceHandler = dh
175 flowMgr.resourceMgr = rsrcMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400176 flowMgr.techprofile = make([]*tp.TechProfileMgr, MaxPonPorts)
manikkaraj kbf256be2019-03-25 00:13:48 +0530177 if err := flowMgr.populateTechProfilePerPonPort(); err != nil {
178 log.Error("Error while populating tech profile mgr\n")
179 return nil
180 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700181 flowMgr.onuIds = make(map[onuIDKey]onuInfo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400182 flowMgr.onuSerialNumbers = make(map[string]onuInfo)
183 flowMgr.onuGemPortIds = make(map[gemPortKey]onuInfo)
184 flowMgr.packetInGemPort = make(map[packetInInfoKey]uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530185 log.Info("Initialization of flow manager success!!")
186 return &flowMgr
187}
188
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700189func (f *OpenOltFlowMgr) generateStoredFlowID(flowID uint32, direction string) (uint64, error) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400190 if direction == UPSTREAM {
191 log.Debug("upstream flow, shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700192 return 0x1<<15 | uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400193 } else if direction == DOWNSTREAM {
194 log.Debug("downstream flow, not shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700195 return uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400196 } else {
197 log.Debug("Unrecognized direction")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700198 return 0, fmt.Errorf("unrecognized direction %s", direction)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400199 }
200}
201
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700202func (f *OpenOltFlowMgr) registerFlow(flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400203 log.Debug("Registering Flow for Device ", log.Fields{"flow": flowFromCore},
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700204 log.Fields{"device": f.deviceHandler.deviceID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400205
206 var storedFlow ofp.OfpFlowStats
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700207 storedFlow.Id, _ = f.generateStoredFlowID(deviceFlow.FlowId, deviceFlow.FlowType)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400208 log.Debug(fmt.Sprintf("Generated stored device flow. id = %d, flowId = %d, direction = %s", storedFlow.Id,
209 deviceFlow.FlowId, deviceFlow.FlowType))
210 storedFlow.Cookie = flowFromCore.Id
211 f.storedDeviceFlows = append(f.storedDeviceFlows, storedFlow)
212 log.Debugw("updated Stored flow info", log.Fields{"storedDeviceFlows": f.storedDeviceFlows})
213}
214
Manikkaraj kb1d51442019-07-23 10:41:02 -0400215func (f *OpenOltFlowMgr) divideAndAddFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpId uint32, UsMeterId uint32, DsMeterId uint32, flowMetadata *voltha.FlowMetadata) {
216 var allocId []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530217 var gemPorts []uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400218 var gemPort uint32
219 var TpInst *tp.TechProfile
manikkaraj kbf256be2019-03-25 00:13:48 +0530220
Manikkaraj kb1d51442019-07-23 10:41:02 -0400221 log.Infow("Dividing flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "portNo": portNo,
222 "classifier": classifierInfo, "action": actionInfo, "UsMeterId": UsMeterId, "DsMeterId": DsMeterId, "TpId": TpId})
Matt Jeanneret77199612019-07-26 18:08:35 -0400223 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
224 // is because the flow is an NNI flow and there would be no onu resources associated with it
225 // TODO: properly deal with NNI flows
Manikkaraj kb1d51442019-07-23 10:41:02 -0400226 if onuID <= 0 {
Matt Jeanneret77199612019-07-26 18:08:35 -0400227 log.Errorw("No onu id for flow", log.Fields{"portNo": portNo, "classifer": classifierInfo, "action": actionInfo})
manikkaraj kbf256be2019-03-25 00:13:48 +0530228 return
229 }
230
Manikkaraj kb1d51442019-07-23 10:41:02 -0400231 uni := getUniPortPath(intfID, onuID, uniID)
232 log.Debugw("Uni port name", log.Fields{"uni": uni})
233 allocId, gemPorts, TpInst = f.createTcontGemports(intfID, onuID, uniID, uni, portNo, TpId, UsMeterId, DsMeterId, flowMetadata)
234 if allocId == nil || gemPorts == nil || TpInst == nil {
235 log.Error("alloc-id-gem-ports-tp-unavailable")
236 return
237 }
238
239 /* Flows can be added specific to gemport if p-bits are received.
240 * If no pbit mentioned then adding flows for all gemports
manikkaraj kbf256be2019-03-25 00:13:48 +0530241 */
Manikkaraj kb1d51442019-07-23 10:41:02 -0400242
243 args := make(map[string]uint32)
244 args["intfId"] = intfID
245 args["onuId"] = onuID
246 args["uniId"] = uniID
247 args["portNo"] = portNo
248 args["allocId"] = allocId[0]
249
250 if ipProto, ok := classifierInfo[IPProto]; ok {
251 if ipProto.(uint32) == IPProtoDhcp {
252 log.Info("Adding DHCP flow")
253 if pcp, ok := classifierInfo[VlanPcp]; ok {
254 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
255 tp_pb.Direction_UPSTREAM,
256 pcp.(uint32))
257 //Adding DHCP upstream flow
258 f.addDHCPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocId[0], gemPort)
manikkaraj kbf256be2019-03-25 00:13:48 +0530259 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400260 //Adding DHCP upstream flow to all gemports
261 installFlowOnAllGemports(f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, DhcpFlow)
manikkaraj kbf256be2019-03-25 00:13:48 +0530262 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400263
264 } else if ipProto == IgmpProto {
265 log.Info("igmp flow add ignored, not implemented yet")
Chaitrashree G S579fe732019-08-20 20:50:47 -0400266 return
manikkaraj kbf256be2019-03-25 00:13:48 +0530267 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400268 log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
Chaitrashree G S579fe732019-08-20 20:50:47 -0400269 return
manikkaraj kbf256be2019-03-25 00:13:48 +0530270 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400271 } else if ethType, ok := classifierInfo[EthType]; ok {
272 if ethType.(uint32) == EapEthType {
273 log.Info("Adding EAPOL flow")
274 var vlanId uint32
275 if val, ok := classifierInfo[VlanVid]; ok {
276 vlanId = (val.(uint32)) & VlanvIDMask
277 } else {
278 vlanId = DefaultMgmtVlan
279 }
280 if pcp, ok := classifierInfo[VlanPcp]; ok {
281 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
282 tp_pb.Direction_UPSTREAM,
283 pcp.(uint32))
284
285 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocId[0], gemPort, vlanId)
286 } else {
287 installFlowOnAllGemports(nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, EapolFlow, vlanId)
288 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400289 }
290 if ethType == LldpEthType {
291 log.Info("Adding LLDP flow")
292 addLLDPFlow(flow, portNo)
Chaitrashree G S579fe732019-08-20 20:50:47 -0400293 return
Manikkaraj kb1d51442019-07-23 10:41:02 -0400294 }
295 } else if _, ok := actionInfo[PushVlan]; ok {
296 log.Info("Adding upstream data rule")
297 if pcp, ok := classifierInfo[VlanPcp]; ok {
298 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
299 tp_pb.Direction_UPSTREAM,
300 pcp.(uint32))
301 //Adding HSIA upstream flow
302 f.addUpstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocId[0], gemPort)
303 } else {
304 //Adding HSIA upstream flow to all gemports
305 installFlowOnAllGemports(f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
306 }
307 } else if _, ok := actionInfo[PopVlan]; ok {
308 log.Info("Adding Downstream data rule")
309 if pcp, ok := classifierInfo[VlanPcp]; ok {
310 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
311 tp_pb.Direction_UPSTREAM,
312 pcp.(uint32))
313 //Adding HSIA downstream flow
314 f.addDownstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocId[0], gemPort)
315 } else {
316 //Adding HSIA downstream flow to all gemports
317 installFlowOnAllGemports(f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
318 }
319 } else {
320 log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
Chaitrashree G S579fe732019-08-20 20:50:47 -0400321 return
manikkaraj kbf256be2019-03-25 00:13:48 +0530322 }
Chaitrashree G S579fe732019-08-20 20:50:47 -0400323 // Send Techprofile download event to child device in go routine as it takes time
324 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, TpId)
manikkaraj kbf256be2019-03-25 00:13:48 +0530325}
326
Manikkaraj kb1d51442019-07-23 10:41:02 -0400327func (f *OpenOltFlowMgr) CreateSchedulerQueues(Dir tp_pb.Direction, IntfId uint32, OnuId uint32, UniId uint32, UniPort uint32, TpInst *tp.TechProfile, MeterId uint32, flowMetadata *voltha.FlowMetadata) error {
328
329 log.Debugw("CreateSchedulerQueues", log.Fields{"Dir": Dir, "IntfId": IntfId, "OnuId": OnuId,
330 "UniId": UniId, "MeterId": MeterId, "TpInst": *TpInst, "flowMetadata": flowMetadata})
331
332 if MeterId == 0 { // This should never happen
333 log.Error("Invalid meter id")
334 return errors.New("Invalid meter id")
335 }
336
337 /* Lets make a simple assumption that if the meter-id is present on the KV store,
338 * then the scheduler and queues configuration is applied on the OLT device
339 * in the given direction.
340 */
341 var Direction string
342 var SchedCfg *tp_pb.SchedulerConfig
343 if Dir == tp_pb.Direction_UPSTREAM {
344 Direction = "upstream"
345 } else if Dir == tp_pb.Direction_DOWNSTREAM {
346 Direction = "downstream"
347 }
348 KvStoreMeter, err := f.resourceMgr.GetMeterIdForOnu(Direction, IntfId, OnuId, UniId)
349 if err != nil {
350 log.Error("Failed to get meter for intf %d, onuid %d, uniid %d", IntfId, OnuId, UniId)
351 return err
352 }
353 if KvStoreMeter != nil {
354 if KvStoreMeter.MeterId == MeterId {
355 log.Debug("Scheduler already created for upstream")
356 return nil
357 } else {
358 log.Errorw("Dynamic meter update not supported", log.Fields{"KvStoreMeterId": KvStoreMeter.MeterId, "MeterId-in-flow": MeterId})
359 return errors.New("Invalid-meter-id-in-flow")
360 }
361 }
362 log.Debugw("Meter-does-not-exist-Creating-new", log.Fields{"MeterId": MeterId, "Direction": Direction})
363 if Dir == tp_pb.Direction_UPSTREAM {
364 SchedCfg = f.techprofile[IntfId].GetUsScheduler(TpInst)
365 } else if Dir == tp_pb.Direction_DOWNSTREAM {
366 SchedCfg = f.techprofile[IntfId].GetDsScheduler(TpInst)
367 }
368 var meterConfig *ofp.OfpMeterConfig
369 if flowMetadata != nil {
370 for _, meter := range flowMetadata.Meters {
371 if MeterId == meter.MeterId {
372 meterConfig = meter
373 log.Debugw("Found-meter-config-from-flowmetadata", log.Fields{"meterConfig": meterConfig})
374 break
375 }
376 }
377 } else {
378 log.Error("Flow-metadata-is-not-present-in-flow")
379 }
380 if meterConfig == nil {
381 log.Errorw("Could-not-get-meterbands-from-flowMetadata", log.Fields{"flowMetadata": flowMetadata, "MeterId": MeterId})
382 return errors.New("Failed-to-get-meter-from-flowMetadata")
383 } else if len(meterConfig.Bands) < MaxMeterBand {
384 log.Errorw("Invalid-number-of-bands-in-meter", log.Fields{"Bands": meterConfig.Bands, "MeterId": MeterId})
385 return errors.New("Invalid-number-of-bands-in-meter")
386 }
387 cir := meterConfig.Bands[0].Rate
388 cbs := meterConfig.Bands[0].BurstSize
389 eir := meterConfig.Bands[1].Rate
390 ebs := meterConfig.Bands[1].BurstSize
391 pir := cir + eir
392 pbs := cbs + ebs
393 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
394
395 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[IntfId].GetTrafficScheduler(TpInst, SchedCfg, TrafficShaping)}
396
397 log.Debugw("Sending Traffic scheduler create to device", log.Fields{"Direction": Direction, "TrafficScheds": TrafficSched})
398 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
399 IntfId: IntfId, OnuId: OnuId,
400 UniId: UniId, PortNo: UniPort,
401 TrafficScheds: TrafficSched}); err != nil {
402 log.Errorw("Failed to create traffic schedulers", log.Fields{"error": err})
403 return err
404 }
405 // On receiving the CreateTrafficQueues request, the driver should create corresponding
406 // downstream queues.
407 trafficQueues := f.techprofile[IntfId].GetTrafficQueues(TpInst, Dir)
408 log.Debugw("Sending Traffic Queues create to device", log.Fields{"Direction": Direction, "TrafficQueues": trafficQueues})
409 if _, err := f.deviceHandler.Client.CreateTrafficQueues(context.Background(),
410 &tp_pb.TrafficQueues{IntfId: IntfId, OnuId: OnuId,
411 UniId: UniId, PortNo: UniPort,
412 TrafficQueues: trafficQueues}); err != nil {
413 log.Errorw("Failed to create traffic queues in device", log.Fields{"error": err})
414 return err
415 }
416
417 /* After we succesfully applied the scheduler configuration on the OLT device,
418 * store the meter id on the KV store, for further reference.
419 */
420 if err := f.resourceMgr.UpdateMeterIdForOnu(Direction, IntfId, OnuId, UniId, meterConfig); err != nil {
421 log.Error("Failed to update meter id for onu %d, meterid %d", OnuId, MeterId)
422 return err
423 }
424 log.Debugw("updated-meter-info into KV store successfully", log.Fields{"Direction": Direction,
425 "Meter": meterConfig})
426 return nil
427}
428
429func (f *OpenOltFlowMgr) RemoveSchedulerQueues(Dir tp_pb.Direction, IntfId uint32, OnuId uint32, UniId uint32, UniPort uint32, TpInst *tp.TechProfile) error {
430
431 var Direction string
432 var SchedCfg *tp_pb.SchedulerConfig
433 var err error
434 log.Debugw("Removing schedulers and Queues in OLT", log.Fields{"Direction": Dir, "IntfId": IntfId, "OnuId": OnuId, "UniId": UniId, "UniPort": UniPort})
435 if Dir == tp_pb.Direction_UPSTREAM {
436 SchedCfg = f.techprofile[IntfId].GetUsScheduler(TpInst)
437 Direction = "upstream"
438 } else if Dir == tp_pb.Direction_DOWNSTREAM {
439 SchedCfg = f.techprofile[IntfId].GetDsScheduler(TpInst)
440 Direction = "downstream"
441 }
442
443 KVStoreMeter, err := f.resourceMgr.GetMeterIdForOnu(Direction, IntfId, OnuId, UniId)
444 if err != nil {
445 log.Errorf("Failed to get Meter for Onu %d", OnuId)
446 return err
447 }
448 if KVStoreMeter == nil {
449 log.Debugw("No-meter-has-been-installed-yet", log.Fields{"direction": Direction, "IntfId": IntfId, "OnuId": OnuId, "UniId": UniId})
450 return nil
451 }
452 cir := KVStoreMeter.Bands[0].Rate
453 cbs := KVStoreMeter.Bands[0].BurstSize
454 eir := KVStoreMeter.Bands[1].Rate
455 ebs := KVStoreMeter.Bands[1].BurstSize
456 pir := cir + eir
457 pbs := cbs + ebs
458
459 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
460
461 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[IntfId].GetTrafficScheduler(TpInst, SchedCfg, TrafficShaping)}
462 TrafficQueues := f.techprofile[IntfId].GetTrafficQueues(TpInst, Dir)
463
464 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(context.Background(),
465 &tp_pb.TrafficQueues{IntfId: IntfId, OnuId: OnuId,
466 UniId: UniId, PortNo: UniPort,
467 TrafficQueues: TrafficQueues}); err != nil {
468 log.Error("Failed to remove traffic queues")
469 return err
470 } else {
471 log.Debug("Removed traffic queues successfully")
472 }
473 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
474 IntfId: IntfId, OnuId: OnuId,
475 UniId: UniId, PortNo: UniPort,
476 TrafficScheds: TrafficSched}); err != nil {
477 log.Error("failed to remove traffic schedulers")
478 return err
479 } else {
480 log.Debug("Removed traffic schedulers successfully")
481 }
482
483 /* After we succesfully remove the scheduler configuration on the OLT device,
484 * delete the meter id on the KV store.
485 */
486 err = f.resourceMgr.RemoveMeterIdForOnu(Direction, IntfId, OnuId, UniId)
487 if err != nil {
488 log.Errorf("Failed to remove meter for onu %d, meter id %d", OnuId, KVStoreMeter.MeterId)
489 }
490 log.Debugw("Removed-meter-from-KV-store successfully", log.Fields{"MeterId": KVStoreMeter.MeterId, "dir": Direction})
491 return err
492}
493
manikkaraj kbf256be2019-03-25 00:13:48 +0530494// This function allocates tconts and GEM ports for an ONU, currently one TCONT is supported per ONU
Manikkaraj kb1d51442019-07-23 10:41:02 -0400495func (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) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530496 var allocID []uint32
497 var gemPortIDs []uint32
498 //If we already have allocated earlier for this onu, render them
Manikkaraj kb1d51442019-07-23 10:41:02 -0400499 if tcontId := f.resourceMgr.GetCurrentAllocIDForOnu(intfID, onuID, uniID); tcontId != 0 {
500 allocID = append(allocID, tcontId)
manikkaraj kbf256be2019-03-25 00:13:48 +0530501 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700502 gemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400503
504 tpPath := f.getTPpath(intfID, uni, TpID)
505 // Check tech profile instance already exists for derived port name
506 tech_profile_instance, err := f.techprofile[intfID].GetTPInstanceFromKVStore(TpID, tpPath)
507 if err != nil { // This should not happen, something wrong in KV backend transaction
508 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": TpID, "path": tpPath})
509 return nil, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530510 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400511
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700512 log.Debug("Creating New TConts and Gem ports", log.Fields{"pon": intfID, "onu": onuID, "uni": uniID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530513
Manikkaraj kb1d51442019-07-23 10:41:02 -0400514 if tech_profile_instance == nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530515 log.Info("Creating tech profile instance", log.Fields{"path": tpPath})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400516 tech_profile_instance = f.techprofile[intfID].CreateTechProfInstance(TpID, uni, intfID)
517 if tech_profile_instance == nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530518 log.Error("Tech-profile-instance-creation-failed")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400519 return nil, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530520 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400521 f.resourceMgr.UpdateTechProfileIdForOnu(intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530522 } else {
523 log.Debugw("Tech-profile-instance-already-exist-for-given port-name", log.Fields{"uni": uni})
524 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400525 if UsMeterID != 0 {
526 if err := f.CreateSchedulerQueues(tp_pb.Direction_UPSTREAM, intfID, onuID, uniID, uniPort, tech_profile_instance, UsMeterID, flowMetadata); err != nil {
527 log.Errorw("CreateSchedulerQueues Failed-upstream", log.Fields{"error": err, "meterID": UsMeterID})
528 return nil, nil, nil
529 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530530 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400531 if DsMeterID != 0 {
532 if err := f.CreateSchedulerQueues(tp_pb.Direction_DOWNSTREAM, intfID, onuID, uniID, uniPort, tech_profile_instance, DsMeterID, flowMetadata); err != nil {
533 log.Errorw("CreateSchedulerQueues Failed-downstream", log.Fields{"error": err, "meterID": DsMeterID})
534 return nil, nil, nil
535 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530536 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400537 if len(allocID) == 0 { // Created TCONT first time
538 allocID = append(allocID, tech_profile_instance.UsScheduler.AllocID)
539 }
540 if len(gemPortIDs) == 0 { // Create GEM ports first time
541 for _, gem := range tech_profile_instance.UpstreamGemPortAttributeList {
542 gemPortIDs = append(gemPortIDs, gem.GemportID)
543 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530544 }
545 log.Debugw("Allocated Tcont and GEM ports", log.Fields{"allocID": allocID, "gemports": gemPortIDs})
546 // Send Tconts and GEM ports to KV store
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700547 f.storeTcontsGEMPortsIntoKVStore(intfID, onuID, uniID, allocID, gemPortIDs)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400548 return allocID, gemPortIDs, tech_profile_instance
manikkaraj kbf256be2019-03-25 00:13:48 +0530549}
550
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700551func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530552
553 log.Debugw("Storing allocated Tconts and GEM ports into KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700554 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "allocID": allocID, "gemPortIDs": gemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530555 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700556 if err := f.resourceMgr.UpdateAllocIdsForOnu(intfID, onuID, uniID, allocID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530557 log.Error("Errow while uploading allocID to KV store")
558 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700559 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(intfID, onuID, uniID, gemPortIDs); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530560 log.Error("Errow while uploading GEMports to KV store")
561 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700562 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(gemPortIDs, intfID, onuID, uniID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530563 log.Error("Errow while uploading gemtopon map to KV store")
564 }
565 log.Debug("Stored tconts and GEM into KV store successfully")
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400566 for _, gemPort := range gemPortIDs {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700567 f.addGemPortToOnuInfoMap(intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400568 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530569}
570
571func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400572 var tpCount int = 0
manikkaraj kbf256be2019-03-25 00:13:48 +0530573 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400574 for _, intfId := range techRange.IntfIds {
575 f.techprofile[intfId] = f.resourceMgr.ResourceMgrs[uint32(intfId)].TechProfileMgr
576 tpCount++
577 log.Debugw("Init tech profile done", log.Fields{"intfId": intfId})
manikkaraj kbf256be2019-03-25 00:13:48 +0530578 }
579 }
580 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400581 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530582 log.Errorw("Error while populating techprofile",
Manikkaraj kb1d51442019-07-23 10:41:02 -0400583 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
584 return errors.New("Error while populating techprofile mgrs")
manikkaraj kbf256be2019-03-25 00:13:48 +0530585 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400586 log.Infow("Populated techprofile for ponports successfully",
587 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
manikkaraj kbf256be2019-03-25 00:13:48 +0530588 return nil
589}
590
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700591func (f *OpenOltFlowMgr) addUpstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530592 portNo uint32, uplinkClassifier map[string]interface{},
593 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700594 allocID uint32, gemportID uint32) {
595 uplinkClassifier[PacketTagType] = SingleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530596 log.Debugw("Adding upstream data flow", log.Fields{"uplinkClassifier": uplinkClassifier, "uplinkAction": uplinkAction})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700597 f.addHSIAFlow(intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
598 UPSTREAM, logicalFlow, allocID, gemportID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530599 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530600}
601
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700602func (f *OpenOltFlowMgr) addDownstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530603 portNo uint32, downlinkClassifier map[string]interface{},
604 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700605 allocID uint32, gemportID uint32) {
606 downlinkClassifier[PacketTagType] = DoubleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530607 log.Debugw("Adding downstream data flow", log.Fields{"downlinkClassifier": downlinkClassifier,
608 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400609 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
610 if vlan, exists := downlinkClassifier[VlanVid]; exists {
611 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
612 if metadata, exists := downlinkClassifier[METADATA]; exists { // inport is filled in metadata by core
613 if uint32(metadata.(uint64)) == MkUniPortNum(intfID, onuID, uniID) {
614 log.Infow("Ignoring DL trap device flow from core", log.Fields{"flow": logicalFlow})
615 return
616 }
617 }
618 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530619 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400620
Manikkaraj k884c1242019-04-11 16:26:42 +0530621 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700622 downlinkAction[PopVlan] = true
623 downlinkAction[VlanVid] = downlinkClassifier[VlanVid]
624 f.addHSIAFlow(intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
625 DOWNSTREAM, logicalFlow, allocID, gemportID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530626}
627
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700628func (f *OpenOltFlowMgr) addHSIAFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +0530629 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700630 allocID uint32, gemPortID uint32) {
Manikkaraj k884c1242019-04-11 16:26:42 +0530631 /* One of the OLT platform (Broadcom BAL) requires that symmetric
632 flows require the same flow_id to be used across UL and DL.
633 Since HSIA flow is the only symmetric flow currently, we need to
634 re-use the flow_id across both direction. The 'flow_category'
635 takes priority over flow_cookie to find any available HSIA_FLOW
636 id for the ONU.
637 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700638 log.Debugw("Adding HSIA flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "classifier": classifier,
639 "action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530640 "logicalFlow": *logicalFlow})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400641 var vlan_pit uint32 = 0
642 if _, ok := classifier[VlanPcp]; ok {
643 vlan_pit = classifier[VlanPcp].(uint32)
644 log.Debugw("Found pbit in the flow", log.Fields{"vlan_pit": vlan_pit})
645 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700646 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400647 flowId, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, HsiaFlow, vlan_pit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530648 if err != nil {
649 log.Errorw("Flow id unavailable for HSIA flow", log.Fields{"direction": direction})
650 return
651 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700652 var classifierProto *openoltpb2.Classifier
653 var actionProto *openoltpb2.Action
Manikkaraj k884c1242019-04-11 16:26:42 +0530654 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
655 log.Error("Error in making classifier protobuf for hsia flow")
656 return
657 }
658 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
659 if actionProto = makeOpenOltActionField(action); actionProto == nil {
660 log.Errorw("Error in making action protobuf for hsia flow", log.Fields{"direction": direction})
661 return
662 }
663 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700664 networkIntfID := f.deviceHandler.nniIntfID
665 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
666 OnuId: int32(onuID),
667 UniId: int32(uniID),
Manikkaraj kb1d51442019-07-23 10:41:02 -0400668 FlowId: flowId,
Manikkaraj k884c1242019-04-11 16:26:42 +0530669 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700670 AllocId: int32(allocID),
671 NetworkIntfId: int32(networkIntfID),
672 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530673 Classifier: classifierProto,
674 Action: actionProto,
675 Priority: int32(logicalFlow.Priority),
676 Cookie: logicalFlow.Cookie,
677 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400678 if ok := f.addFlowToDevice(logicalFlow, &flow); ok {
Manikkaraj k884c1242019-04-11 16:26:42 +0530679 log.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400680 flowsToKVStore := f.getUpdatedFlowInfo(&flow, flowStoreCookie, HsiaFlow, flowId)
Manikkaraj k884c1242019-04-11 16:26:42 +0530681 if err := f.updateFlowInfoToKVStore(flow.AccessIntfId,
682 flow.OnuId,
683 flow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400684 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530685 log.Errorw("Error uploading HSIA flow into KV store", log.Fields{"flow": flow, "direction": direction, "error": err})
686 return
687 }
688 }
689}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700690func (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 +0530691
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700692 var dhcpFlow openoltpb2.Flow
693 var actionProto *openoltpb2.Action
694 var classifierProto *openoltpb2.Classifier
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530695
696 // Clear the action map
697 for k := range action {
698 delete(action, k)
699 }
700
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700701 action[TrapToHost] = true
702 classifier[UDPSrc] = uint32(68)
703 classifier[UDPDst] = uint32(67)
704 classifier[PacketTagType] = SingleTag
705 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530706
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700707 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530708
Manikkaraj kb1d51442019-07-23 10:41:02 -0400709 flowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, "", 0 /*classifier[VLAN_PCP].(uint32)*/)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530710
711 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700712 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530713 return
714 }
715
716 log.Debugw("Creating UL DHCP flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID})
717
718 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
719 log.Error("Error in making classifier protobuf for ul flow")
720 return
721 }
722 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
723 if actionProto = makeOpenOltActionField(action); actionProto == nil {
724 log.Error("Error in making action protobuf for ul flow")
725 return
726 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700727 networkIntfID := f.deviceHandler.nniIntfID
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530728
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700729 dhcpFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
730 OnuId: int32(onuID),
731 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530732 FlowId: flowID,
733 FlowType: UPSTREAM,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700734 AllocId: int32(allocID),
735 NetworkIntfId: int32(networkIntfID),
736 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530737 Classifier: classifierProto,
738 Action: actionProto,
739 Priority: int32(logicalFlow.Priority),
740 Cookie: logicalFlow.Cookie,
741 PortNo: portNo}
742
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400743 if ok := f.addFlowToDevice(logicalFlow, &dhcpFlow); ok {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530744 log.Debug("DHCP UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400745 flowsToKVStore := f.getUpdatedFlowInfo(&dhcpFlow, flowStoreCookie, "DHCP", flowID)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530746 if err := f.updateFlowInfoToKVStore(dhcpFlow.AccessIntfId,
747 dhcpFlow.OnuId,
748 dhcpFlow.UniId,
749 dhcpFlow.FlowId, flowsToKVStore); err != nil {
750 log.Errorw("Error uploading DHCP UL flow into KV store", log.Fields{"flow": dhcpFlow, "error": err})
751 return
752 }
753 }
754
manikkaraj kbf256be2019-03-25 00:13:48 +0530755 return
756}
757
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700758// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
759func (f *OpenOltFlowMgr) addEAPOLFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, vlanID uint32) {
760 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 +0530761
762 uplinkClassifier := make(map[string]interface{})
763 uplinkAction := make(map[string]interface{})
764 downlinkClassifier := make(map[string]interface{})
765 downlinkAction := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700766 var upstreamFlow openoltpb2.Flow
767 var downstreamFlow openoltpb2.Flow
manikkaraj kbf256be2019-03-25 00:13:48 +0530768
769 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700770 uplinkClassifier[EthType] = uint32(EapEthType)
771 uplinkClassifier[PacketTagType] = SingleTag
772 uplinkClassifier[VlanVid] = vlanID
manikkaraj kbf256be2019-03-25 00:13:48 +0530773 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700774 uplinkAction[TrapToHost] = true
775 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530776 //Add Uplink EAPOL Flow
Manikkaraj kb1d51442019-07-23 10:41:02 -0400777 uplinkFlowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530778 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700779 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manikkaraj k884c1242019-04-11 16:26:42 +0530780 return
manikkaraj kbf256be2019-03-25 00:13:48 +0530781 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700782 var classifierProto *openoltpb2.Classifier
783 var actionProto *openoltpb2.Action
784 log.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530785
786 if classifierProto = makeOpenOltClassifierField(uplinkClassifier); classifierProto == nil {
787 log.Error("Error in making classifier protobuf for ul flow")
788 return
789 }
790 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
791 if actionProto = makeOpenOltActionField(uplinkAction); actionProto == nil {
792 log.Error("Error in making action protobuf for ul flow")
793 return
794 }
795 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700796 networkIntfID := f.deviceHandler.nniIntfID
797 upstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
798 OnuId: int32(onuID),
799 UniId: int32(uniID),
800 FlowId: uplinkFlowID,
manikkaraj kbf256be2019-03-25 00:13:48 +0530801 FlowType: UPSTREAM,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700802 AllocId: int32(allocID),
803 NetworkIntfId: int32(networkIntfID),
804 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530805 Classifier: classifierProto,
806 Action: actionProto,
807 Priority: int32(logicalFlow.Priority),
808 Cookie: logicalFlow.Cookie,
809 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400810 if ok := f.addFlowToDevice(logicalFlow, &upstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530811 log.Debug("EAPOL UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400812 flowCategory := "EAPOL"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700813 flowsToKVStore := f.getUpdatedFlowInfo(&upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530814 if err := f.updateFlowInfoToKVStore(upstreamFlow.AccessIntfId,
815 upstreamFlow.OnuId,
816 upstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400817 upstreamFlow.FlowId,
818 /* lowCategory, */
819 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530820 log.Errorw("Error uploading EAPOL UL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
821 return
822 }
823 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400824 // Dummy Downstream flow due to BAL 2.6 limitation
825 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530826 /* Add Downstream EAPOL Flow, Only for first EAP flow (BAL
827 # requirement)
828 # On one of the platforms (Broadcom BAL), when same DL classifier
829 # vlan was used across multiple ONUs, eapol flow re-adds after
830 # flow delete (cases of onu reboot/disable) fails.
831 # In order to generate unique vlan, a combination of intf_id
832 # onu_id and uniId is used.
833 # uniId defaults to 0, so add 1 to it.
834 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700835 log.Debugw("Creating DL EAPOL flow with default vlan", log.Fields{"vlan": vlanID})
836 specialVlanDlFlow := 4090 - intfID*onuID*(uniID+1)
manikkaraj kbf256be2019-03-25 00:13:48 +0530837 // Assert that we do not generate invalid vlans under no condition
838 if specialVlanDlFlow <= 2 {
839 log.Fatalw("invalid-vlan-generated", log.Fields{"vlan": specialVlanDlFlow})
840 return
841 }
842 log.Debugw("specialVlanEAPOLDlFlow:", log.Fields{"dl_vlan": specialVlanDlFlow})
843 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700844 downlinkClassifier[PacketTagType] = SingleTag
Manikkaraj kb1d51442019-07-23 10:41:02 -0400845 downlinkClassifier[EthType] = uint32(EapEthType)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700846 downlinkClassifier[VlanVid] = uint32(specialVlanDlFlow)
manikkaraj kbf256be2019-03-25 00:13:48 +0530847 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700848 downlinkAction[PushVlan] = true
849 downlinkAction[VlanVid] = vlanID
850 flowStoreCookie := getFlowStoreCookie(downlinkClassifier, gemPortID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400851 downlinkFlowId, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530852 if err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530853 log.Errorw("flowId unavailable for DL EAPOL",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700854 log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
manikkaraj kbf256be2019-03-25 00:13:48 +0530855 return
856 }
857 log.Debugw("Creating DL EAPOL flow",
Manikkaraj kb1d51442019-07-23 10:41:02 -0400858 log.Fields{"dl_classifier": downlinkClassifier, "dl_action": downlinkAction, "downlinkFlowId": downlinkFlowId})
manikkaraj kbf256be2019-03-25 00:13:48 +0530859 if classifierProto = makeOpenOltClassifierField(downlinkClassifier); classifierProto == nil {
860 log.Error("Error in making classifier protobuf for downlink flow")
861 return
862 }
863 if actionProto = makeOpenOltActionField(downlinkAction); actionProto == nil {
864 log.Error("Error in making action protobuf for dl flow")
865 return
866 }
867 // Downstream flow in grpc protobuf
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700868 downstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
869 OnuId: int32(onuID),
870 UniId: int32(uniID),
Manikkaraj kb1d51442019-07-23 10:41:02 -0400871 FlowId: downlinkFlowId,
manikkaraj kbf256be2019-03-25 00:13:48 +0530872 FlowType: DOWNSTREAM,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700873 AllocId: int32(allocID),
874 NetworkIntfId: int32(networkIntfID),
875 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530876 Classifier: classifierProto,
877 Action: actionProto,
878 Priority: int32(logicalFlow.Priority),
879 Cookie: logicalFlow.Cookie,
880 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400881 if ok := f.addFlowToDevice(logicalFlow, &downstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530882 log.Debug("EAPOL DL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400883 flowCategory := ""
Manikkaraj kb1d51442019-07-23 10:41:02 -0400884 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamFlow, flowStoreCookie, flowCategory, downlinkFlowId)
manikkaraj kbf256be2019-03-25 00:13:48 +0530885 if err := f.updateFlowInfoToKVStore(downstreamFlow.AccessIntfId,
886 downstreamFlow.OnuId,
887 downstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400888 downstreamFlow.FlowId,
889 /* flowCategory, */
890 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530891 log.Errorw("Error uploading EAPOL DL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
892 return
893 }
894 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530895 }
896 log.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
897}
898
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700899func makeOpenOltClassifierField(classifierInfo map[string]interface{}) *openoltpb2.Classifier {
900 var classifier openoltpb2.Classifier
901 if etherType, ok := classifierInfo[EthType]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530902 classifier.EthType = etherType.(uint32)
903 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700904 if ipProto, ok := classifierInfo[IPProto]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530905 classifier.IpProto = ipProto.(uint32)
906 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700907 if vlanID, ok := classifierInfo[VlanVid]; ok {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400908 classifier.OVid = (vlanID.(uint32)) & VlanvIDMask
manikkaraj kbf256be2019-03-25 00:13:48 +0530909 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400910 if metadata, ok := classifierInfo[METADATA]; ok {
Manikkaraj k884c1242019-04-11 16:26:42 +0530911 classifier.IVid = uint32(metadata.(uint64))
manikkaraj kbf256be2019-03-25 00:13:48 +0530912 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700913 if vlanPcp, ok := classifierInfo[VlanPcp]; ok {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400914 if vlanPcp == 0 {
915 classifier.OPbits = VlanPCPMask
916 } else {
917 classifier.OPbits = (vlanPcp.(uint32)) & VlanPCPMask
918 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530919 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700920 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530921 classifier.SrcPort = udpSrc.(uint32)
922 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700923 if udpDst, ok := classifierInfo[UDPDst]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530924 classifier.DstPort = udpDst.(uint32)
925 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700926 if ipv4Dst, ok := classifierInfo[Ipv4Dst]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530927 classifier.DstIp = ipv4Dst.(uint32)
928 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700929 if ipv4Src, ok := classifierInfo[Ipv4Src]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530930 classifier.SrcIp = ipv4Src.(uint32)
931 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700932 if pktTagType, ok := classifierInfo[PacketTagType]; ok {
933 if pktTagType.(string) == SingleTag {
934 classifier.PktTagType = SingleTag
935 } else if pktTagType.(string) == DoubleTag {
936 classifier.PktTagType = DoubleTag
manikkaraj kbf256be2019-03-25 00:13:48 +0530937 } else if pktTagType.(string) == UNTAGGED {
938 classifier.PktTagType = UNTAGGED
939 } else {
940 log.Error("Invalid tag type in classifier") // should not hit
941 return nil
942 }
943 }
944 return &classifier
945}
946
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700947func makeOpenOltActionField(actionInfo map[string]interface{}) *openoltpb2.Action {
948 var actionCmd openoltpb2.ActionCmd
949 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +0530950 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700951 if _, ok := actionInfo[PopVlan]; ok {
952 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530953 action.Cmd.RemoveOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700954 } else if _, ok := actionInfo[PushVlan]; ok {
955 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530956 action.Cmd.AddOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700957 } else if _, ok := actionInfo[TrapToHost]; ok {
958 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +0530959 } else {
960 log.Errorw("Invalid-action-field", log.Fields{"action": actionInfo})
961 return nil
962 }
963 return &action
964}
965
Manikkaraj kb1d51442019-07-23 10:41:02 -0400966func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uni string, TpID uint32) string {
967 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530968}
969
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700970func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530971 if len(classifier) == 0 { // should never happen
972 log.Error("Invalid classfier object")
973 return 0
974 }
975 var jsonData []byte
976 var flowString string
977 var err error
978 // TODO: Do we need to marshall ??
979 if jsonData, err = json.Marshal(classifier); err != nil {
980 log.Error("Failed to encode classifier")
981 return 0
982 }
983 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700984 if gemPortID != 0 {
985 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +0530986 }
987 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700988 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +0530989 hash := big.NewInt(0)
990 hash.SetBytes(h.Sum(nil))
991 return hash.Uint64()
992}
993
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700994func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openoltpb2.Flow, flowStoreCookie uint64, flowCategory string, deviceFlowID uint32) *[]rsrcMgr.FlowInfo {
995 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
996 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400997 /* For flows which trap out of the NNI, the AccessIntfId is invalid
998 (set to -1). In such cases, we need to refer to the NetworkIntfId .
999 */
1000 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001001 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001002 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001003 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001004 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001005 // Get existing flows matching flowid for given subscriber from KV store
1006 existingFlows := f.resourceMgr.GetFlowIDInfo(intfID, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001007 if existingFlows != nil {
1008 log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001009 //for _, f := range *existingFlows {
1010 // flows = append(flows, f)
1011 //}
1012 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001013 }
1014 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 +05301015 return &flows
1016}
1017
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001018//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
1019// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
1020// var intfId uint32
1021// /* For flows which trap out of the NNI, the AccessIntfId is invalid
1022// (set to -1). In such cases, we need to refer to the NetworkIntfId .
1023// */
1024// if flow.AccessIntfId != -1 {
1025// intfId = uint32(flow.AccessIntfId)
1026// } else {
1027// intfId = uint32(flow.NetworkIntfId)
1028// }
1029// // Get existing flows matching flowid for given subscriber from KV store
1030// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
1031// if existingFlows != nil {
1032// log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
1033// for _, f := range *existingFlows {
1034// flows = append(flows, f)
1035// }
1036// }
1037// log.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
1038// return &flows
1039//}
1040
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001041func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
manikkaraj k17652a72019-05-06 09:06:36 -04001042 log.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001043 if err := f.resourceMgr.UpdateFlowIDInfo(intfID, onuID, uniID, flowID, flows); err != nil {
manikkaraj k17652a72019-05-06 09:06:36 -04001044 log.Debug("Error while Storing flow into KV store")
1045 return err
1046 }
1047 log.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +05301048 return nil
1049}
1050
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001051func (f *OpenOltFlowMgr) addFlowToDevice(logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) bool {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001052
1053 var intfID uint32
1054 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1055 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1056 */
1057 if deviceFlow.AccessIntfId != -1 {
1058 intfID = uint32(deviceFlow.AccessIntfId)
1059 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001060 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001061 intfID = uint32(deviceFlow.NetworkIntfId)
1062 }
1063
manikkaraj kbf256be2019-03-25 00:13:48 +05301064 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1065 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001066
1067 st, _ := status.FromError(err)
1068 if st.Code() == codes.AlreadyExists {
1069 log.Debug("Flow already exixts", log.Fields{"err": err, "deviceFlow": deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301070 return false
1071 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001072
1073 if err != nil {
1074 log.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": deviceFlow})
1075 f.resourceMgr.FreeFlowID(intfID, uint32(deviceFlow.OnuId), uint32(deviceFlow.UniId), deviceFlow.FlowId)
1076 return false
1077 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001078 log.Debugw("Flow added to device successfully ", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001079 f.registerFlow(logicalFlow, deviceFlow)
1080 return true
1081}
1082
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001083func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) bool {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001084 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1085 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1086 if err != nil {
1087 log.Errorw("Failed to Remove flow from device", log.Fields{"err": err, "deviceFlow": deviceFlow})
1088 return false
1089 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001090 log.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301091 return true
1092}
1093
1094/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1095 //update core flows_proxy : flows_proxy.update('/', flows)
1096}
1097
1098func generateStoredId(flowId uint32, direction string)uint32{
1099
1100 if direction == UPSTREAM{
1101 log.Debug("Upstream flow shifting flowid")
1102 return ((0x1 << 15) | flowId)
1103 }else if direction == DOWNSTREAM{
1104 log.Debug("Downstream flow not shifting flowid")
1105 return flowId
1106 }else{
1107 log.Errorw("Unrecognized direction",log.Fields{"direction": direction})
1108 return flowId
1109 }
1110}
1111
1112*/
1113
1114func addLLDPFlow(flow *ofp.OfpFlowStats, portNo uint32) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001115 log.Info("unimplemented flow : %v, portNo : %v ", flow, portNo)
manikkaraj kbf256be2019-03-25 00:13:48 +05301116}
1117
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001118func getUniPortPath(intfID uint32, onuID uint32, uniID uint32) string {
1119 return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1120}
1121
1122//getOnuChildDevice to fetch onu
1123func (f *OpenOltFlowMgr) getOnuChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
1124 log.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
1125 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
1126 onuDevice := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301127 if onuDevice == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001128 log.Errorw("onu not found", log.Fields{"intfId": parentPortNo, "onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301129 return nil, errors.New("onu not found")
manikkaraj kbf256be2019-03-25 00:13:48 +05301130 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301131 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1132 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301133}
1134
1135func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001136 log.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301137 return nil
1138}
1139
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001140func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
1141 log.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301142}
1143
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001144func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001145 if id>>15 == 0x1 {
1146 return id & 0x7fff, UPSTREAM
1147 }
1148 return id, DOWNSTREAM
1149}
1150
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001151func (f *OpenOltFlowMgr) clearFlowFromResourceManager(flow *ofp.OfpFlowStats, flowID uint32, flowDirection string) {
1152 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowID": flowID, "flowDirection": flowDirection, "flow": *flow})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001153 portNum, ponIntf, onuID, uniID, err := FlowExtractInfo(flow, flowDirection)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001154 if err != nil {
1155 log.Error(err)
1156 return
1157 }
1158 log.Debugw("Extracted access info from flow to be deleted",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001159 log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001160
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001161 flowsInfo := f.resourceMgr.GetFlowIDInfo(ponIntf, onuID, uniID, flowID)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001162 if flowsInfo == nil {
1163 log.Debugw("No FlowInfo found found in KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001164 log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001165 return
1166 }
1167 var updatedFlows []rsrcMgr.FlowInfo
1168
1169 for _, flow := range *flowsInfo {
1170 updatedFlows = append(updatedFlows, flow)
1171 }
1172
1173 for i, storedFlow := range updatedFlows {
1174 if flowDirection == storedFlow.Flow.FlowType {
1175 //Remove the Flow from FlowInfo
1176 log.Debugw("Removing flow to be deleted", log.Fields{"flow": storedFlow})
1177 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1178 break
1179 }
1180 }
1181
1182 if len(updatedFlows) >= 0 {
1183 // There are still flows referencing the same flow_id.
1184 // So the flow should not be freed yet.
1185 // For ex: Case of HSIA where same flow is shared
1186 // between DS and US.
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001187 f.updateFlowInfoToKVStore(int32(ponIntf), int32(onuID), int32(uniID), flowID, &updatedFlows)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001188 if len(updatedFlows) == 0 {
1189 log.Debugw("Releasing flow Id to resource manager", log.Fields{"ponIntf": ponIntf, "onuId": onuID, "uniId": uniID, "flowId": flowID})
1190 f.resourceMgr.FreeFlowID(ponIntf, onuID, uniID, flowID)
1191 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001192 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001193 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ponIntf, onuID, uniID)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001194 if len(flowIds) == 0 {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001195 log.Debugf("Flow count for subscriber %d is zero", onuID)
1196 kvstoreTpId := f.resourceMgr.GetTechProfileIdForOnu(ponIntf, onuID, uniID)
1197 if kvstoreTpId == 0 {
1198 log.Warnw("Could-not-find-techprofile-tableid-for-uni", log.Fields{"ponIntf": ponIntf, "onuId": onuID, "uniId": uniID})
1199 return
1200 }
1201 uni := getUniPortPath(ponIntf, onuID, uniID)
1202 tpPath := f.getTPpath(ponIntf, uni, kvstoreTpId)
1203 log.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
1204 techprofileInst, err := f.techprofile[ponIntf].GetTPInstanceFromKVStore(kvstoreTpId, tpPath)
1205 if err != nil { // This should not happen, something wrong in KV backend transaction
1206 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": 20, "path": tpPath})
1207 return
1208 }
1209 if techprofileInst == nil {
1210 log.Errorw("Tech-profile-instance-does-not-exist-in-KV Store", log.Fields{"tpPath": tpPath})
1211 return
1212 }
1213
1214 f.RemoveSchedulerQueues(tp_pb.Direction_UPSTREAM, ponIntf, onuID, uniID, portNum, techprofileInst)
1215 f.RemoveSchedulerQueues(tp_pb.Direction_DOWNSTREAM, ponIntf, onuID, uniID, portNum, techprofileInst)
1216 } else {
1217 log.Debugf("Flow ids for subscriber", log.Fields{"onu": onuID, "flows": flowIds})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001218 }
1219}
1220
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001221//RemoveFlow removes the flow from the device
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001222func (f *OpenOltFlowMgr) RemoveFlow(flow *ofp.OfpFlowStats) {
1223 log.Debugw("Removing Flow", log.Fields{"flow": flow})
1224 var deviceFlowsToRemove []ofp.OfpFlowStats
1225 var deletedFlowsIdx []int
1226 for _, curFlow := range f.storedDeviceFlows {
1227 if curFlow.Cookie == flow.Id {
1228 log.Debugw("Found found matching flow-cookie", log.Fields{"curFlow": curFlow})
1229 deviceFlowsToRemove = append(deviceFlowsToRemove, curFlow)
1230 }
1231 }
1232 log.Debugw("Flows to be deleted", log.Fields{"deviceFlowsToRemove": deviceFlowsToRemove})
1233 for index, curFlow := range deviceFlowsToRemove {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001234 id, direction := f.decodeStoredID(curFlow.GetId())
1235 removeFlowMessage := openoltpb2.Flow{FlowId: uint32(id), FlowType: direction}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001236 if ok := f.removeFlowFromDevice(&removeFlowMessage); ok {
1237 log.Debug("Flow removed from device successfully")
1238 deletedFlowsIdx = append(deletedFlowsIdx, index)
1239 f.clearFlowFromResourceManager(flow, uint32(id), direction) //TODO: Take care of the limitations
1240 }
1241
1242 }
1243 // Can be done in separate go routine as it takes time ?
1244 for _, flowToRemove := range deletedFlowsIdx {
1245 for index, storedFlow := range f.storedDeviceFlows {
1246 if deviceFlowsToRemove[flowToRemove].Cookie == storedFlow.Cookie {
1247 log.Debugw("Removing flow from local Store", log.Fields{"flow": storedFlow})
1248 f.storedDeviceFlows = append(f.storedDeviceFlows[:index], f.storedDeviceFlows[index+1:]...)
1249 break
1250 }
1251 }
1252 }
1253 log.Debugw("Flows removed from the data store",
1254 log.Fields{"number_of_flows_removed": len(deviceFlowsToRemove), "updated_stored_flows": f.storedDeviceFlows})
1255 return
1256}
1257
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001258// AddFlow add flow to device
Manikkaraj kb1d51442019-07-23 10:41:02 -04001259func (f *OpenOltFlowMgr) AddFlow(flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001260 classifierInfo := make(map[string]interface{})
1261 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001262 var UsMeterID uint32
1263 var DsMeterID uint32
1264
1265 log.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
Matt Jeannereta93dbed2019-05-17 12:40:05 -04001266 for _, field := range utils.GetOfbFields(flow) {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001267 if field.Type == utils.ETH_TYPE {
1268 classifierInfo[EthType] = field.GetEthType()
1269 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
1270 } else if field.Type == utils.IP_PROTO {
1271 classifierInfo[IPProto] = field.GetIpProto()
1272 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
1273 } else if field.Type == utils.IN_PORT {
1274 classifierInfo[InPort] = field.GetPort()
1275 log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
1276 } else if field.Type == utils.VLAN_VID {
1277 classifierInfo[VlanVid] = field.GetVlanVid()
1278 log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
1279 } else if field.Type == utils.VLAN_PCP {
1280 classifierInfo[VlanPcp] = field.GetVlanPcp()
1281 log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
1282 } else if field.Type == utils.UDP_DST {
1283 classifierInfo[UDPDst] = field.GetUdpDst()
1284 log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
1285 } else if field.Type == utils.UDP_SRC {
1286 classifierInfo[UDPSrc] = field.GetUdpSrc()
1287 log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
1288 } else if field.Type == utils.IPV4_DST {
1289 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
1290 log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
1291 } else if field.Type == utils.IPV4_SRC {
1292 classifierInfo[Ipv4Src] = field.GetIpv4Src()
1293 log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
1294 } else if field.Type == utils.METADATA {
1295 classifierInfo[METADATA] = field.GetTableMetadata()
1296 log.Debug("field-type-metadata", log.Fields{"classifierInfo[METADATA]": classifierInfo[METADATA].(uint64)})
1297 } else if field.Type == utils.TUNNEL_ID {
1298 classifierInfo[TunnelID] = field.GetTunnelId()
1299 log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
1300 } else {
1301 log.Errorw("Un supported field type", log.Fields{"type": field.Type})
1302 return
1303 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301304 }
Matt Jeannereta93dbed2019-05-17 12:40:05 -04001305 for _, action := range utils.GetActions(flow) {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001306 if action.Type == utils.OUTPUT {
1307 if out := action.GetOutput(); out != nil {
1308 actionInfo[OUTPUT] = out.GetPort()
1309 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[OUTPUT].(uint32)})
1310 } else {
1311 log.Error("Invalid output port in action")
1312 return
1313 }
1314 } else if action.Type == utils.POP_VLAN {
1315 actionInfo[PopVlan] = true
1316 log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
1317 } else if action.Type == utils.PUSH_VLAN {
1318 if out := action.GetPush(); out != nil {
1319 if tpid := out.GetEthertype(); tpid != 0x8100 {
1320 log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
1321 } else {
1322 actionInfo[PushVlan] = true
1323 actionInfo[TPID] = tpid
1324 log.Debugw("action-type-push-vlan",
1325 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
1326 }
1327 }
1328 } else if action.Type == utils.SET_FIELD {
1329 if out := action.GetSetField(); out != nil {
1330 if field := out.GetField(); field != nil {
1331 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
1332 log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
1333 return
1334 }
1335 /*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
1336 if ofbField := field.GetOfbField(); ofbField != nil {
1337 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
1338 if vlan := ofbField.GetVlanVid(); vlan != 0 {
1339 actionInfo[VlanVid] = vlan & 0xfff
1340 log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
1341 } else {
1342 log.Error("No Invalid vlan id in set vlan-vid action")
1343 }
1344 } else {
1345 log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
1346 }
1347 }
1348 }
1349 }
1350 } else {
1351 log.Errorw("Un supported action type", log.Fields{"type": action.Type})
1352 return
1353 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301354 }
manikkaraj k17652a72019-05-06 09:06:36 -04001355 /* Controller bound trap flows */
1356 if isControllerFlow := IsControllerBoundFlow(actionInfo[OUTPUT].(uint32)); isControllerFlow {
1357 log.Debug("Controller bound trap flows, getting inport from tunnelid")
1358 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001359 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Matt Jeannereta93dbed2019-05-17 12:40:05 -04001360 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001361 classifierInfo[InPort] = uniPort
1362 log.Debugw("upstream pon-to-controller-flow,inport-in-tunnelid", log.Fields{"newInPort": classifierInfo[InPort].(uint32), "outPort": actionInfo[OUTPUT].(uint32)})
manikkaraj kbf256be2019-03-25 00:13:48 +05301363 } else {
manikkaraj k17652a72019-05-06 09:06:36 -04001364 log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1365 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301366 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001367 } /*else {
1368 log.Debugw("Trap on NNI flow currently not supported", log.Fields{"flow": *flow})
1369 return
1370 }*/
manikkaraj k17652a72019-05-06 09:06:36 -04001371 } else {
1372 log.Debug("Non-Controller flows, getting uniport from tunnelid")
1373 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001374 if portType := IntfIDToPortTypeName(actionInfo[OUTPUT].(uint32)); portType == voltha.Port_PON_OLT {
Matt Jeannereta93dbed2019-05-17 12:40:05 -04001375 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
manikkaraj k17652a72019-05-06 09:06:36 -04001376 actionInfo[OUTPUT] = uniPort
1377 log.Debugw("downstream-nni-to-pon-port-flow, outport-in-tunnelid", log.Fields{"newOutPort": actionInfo[OUTPUT].(uint32), "outPort": actionInfo[OUTPUT].(uint32)})
1378 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001379 log.Debug("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid", log.Fields{"InPort": classifierInfo[InPort].(uint32), "outPort": actionInfo[OUTPUT].(uint32)})
manikkaraj k17652a72019-05-06 09:06:36 -04001380 return
1381 }
1382 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001383 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Matt Jeannereta93dbed2019-05-17 12:40:05 -04001384 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001385 classifierInfo[InPort] = uniPort
manikkaraj k17652a72019-05-06 09:06:36 -04001386 log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[OUTPUT].(uint32),
1387 "outport": actionInfo[OUTPUT].(uint32)})
1388 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001389 log.Debug("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid", log.Fields{"InPort": classifierInfo[InPort].(uint32),
manikkaraj k17652a72019-05-06 09:06:36 -04001390 "outPort": actionInfo[OUTPUT].(uint32)})
1391 return
1392 }
1393 }
1394 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001395 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[OUTPUT]})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001396 portNo, intfId, onuId, uniId := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[OUTPUT].(uint32))
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001397 if ipProto, ok := classifierInfo[IPProto]; ok {
1398 if ipProto.(uint32) == IPProtoDhcp {
1399 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001400 if udpSrc.(uint32) == uint32(67) {
1401 log.Debug("trap-dhcp-from-nni-flow")
1402 f.addDHCPTrapFlowOnNNI(flow, classifierInfo, portNo)
1403 return
1404 }
1405 }
1406 }
1407 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001408 /* Metadata 8 bytes:
1409 Most Significant 2 Bytes = Inner VLAN
1410 Next 2 Bytes = Tech Profile ID(TPID)
1411 Least Significant 4 Bytes = Port ID
1412 Flow METADATA carries Tech-Profile (TP) ID and is mandatory in all
1413 subscriber related flows.
1414 */
1415 metadata := utils.GetMetadataFromWriteMetadataAction(flow)
1416 if metadata == 0 {
1417 log.Error("Metadata is not present in flow which is mandatory")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001418 return
1419 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001420 TpID := utils.GetTechProfileIDFromWriteMetaData(metadata)
1421 kvstoreTpId := f.resourceMgr.GetTechProfileIdForOnu(intfId, onuId, uniId)
1422 if kvstoreTpId == 0 {
1423 log.Debugf("tpid-not-present-in-kvstore, using tp id %d from flow metadata", TpID)
1424 } else if kvstoreTpId != uint32(TpID) {
1425 log.Error(" Tech-profile-updates-not-supported", log.Fields{"Tpid-in-flow": TpID, "kvstore-TpId": kvstoreTpId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001426 return
1427 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001428 log.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfId, "onuId": onuId, "uniId": uniId})
1429 if IsUpstream(actionInfo[OUTPUT].(uint32)) {
1430 UsMeterID = utils.GetMeterIdFromFlow(flow)
1431 log.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
1432 } else {
1433 DsMeterID = utils.GetMeterIdFromFlow(flow)
1434 log.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
1435
1436 }
1437 f.divideAndAddFlow(intfId, onuId, uniId, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001438}
1439
1440//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04001441func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001442
1443 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301444 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001445 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301446 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301447 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301448 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04001449
Manikkaraj kb1d51442019-07-23 10:41:02 -04001450 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001451 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
manikkaraj k17652a72019-05-06 09:06:36 -04001452 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
1453 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1454 tpDownloadMsg,
1455 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
1456 f.deviceHandler.deviceType,
1457 onuDevice.Type,
1458 onuDevice.Id,
1459 onuDevice.ProxyAddress.DeviceId, "")
1460 if sendErr != nil {
1461 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1462 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1463 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1464 return sendErr
1465 }
1466 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05301467 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301468}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001469
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001470//UpdateOnuInfo function adds onu info to cache
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001471func (f *OpenOltFlowMgr) UpdateOnuInfo(intfID uint32, onuID uint32, serialNum string) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001472 onu := onuInfo{intfID: intfID, onuID: onuID, serialNumber: serialNum}
1473 onuIDkey := onuIDKey{intfID: intfID, onuID: onuID}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001474 f.onuIds[onuIDkey] = onu
1475 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
1476}
1477
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001478//addGemPortToOnuInfoMap function stores adds GEMport to ONU map
1479func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(intfID uint32, onuID uint32, gemPort uint32) {
1480 onuIDkey := onuIDKey{intfID: intfID, onuID: onuID}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001481 if val, ok := f.onuIds[onuIDkey]; ok {
1482 onuInfo := val
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001483 gemportKey := gemPortKey{intfID: intfID, gemPort: gemPort}
1484 f.onuGemPortIds[gemportKey] = onuInfo
1485 log.Debugw("Cached Gemport to Onuinfo map", log.Fields{"GemPort": gemPort, "intfId": onuInfo.intfID, "onuId": onuInfo.onuID})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001486 return
1487 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001488 log.Errorw("OnuInfo not found", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001489}
1490
1491// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001492
1493//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
1494func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
1495 log.Debugw("Getting ONU ID from GEM port and PON port", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPortId": gemPortID})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001496 if serialNumber != "" {
1497 if onuInfo, ok := f.onuSerialNumbers[serialNumber]; ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001498 return onuInfo.onuID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001499 }
1500 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001501 gemportKey := gemPortKey{intfID: intfID, gemPort: gemPortID}
1502 if onuInfo, ok := f.onuGemPortIds[gemportKey]; ok {
1503 log.Debugw("Retrieved onu info from access", log.Fields{"intfId": intfID, "gemPortId": gemPortID, "onuId": onuInfo.onuID})
1504 return onuInfo.onuID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001505 }
1506 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001507 log.Errorw("onuid is not found", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPort": gemPortID})
1508 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 -04001509}
1510
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001511//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
1512func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001513 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001514 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001515 var err error
1516
1517 if packetIn.IntfType == "pon" {
1518 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001519 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001520 log.Errorw("Unable to get ONU ID from GEM/PON port", log.Fields{"pon port": packetIn.IntfId, "gemport": packetIn.GemportId})
1521 return logicalPortNum, err
1522 }
1523 if packetIn.PortNo != 0 {
1524 logicalPortNum = packetIn.PortNo
1525 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001526 uniID := uint32(0) // FIXME - multi-uni support
1527 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001528 }
1529 // Store the gem port through which the packet_in came. Use the same gem port for packet_out
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001530 pktInkey := packetInInfoKey{intfID: packetIn.IntfId, onuID: onuID, logicalPort: logicalPortNum}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001531 f.packetInGemPort[pktInkey] = packetIn.GemportId
1532 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001533 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001534 }
1535 log.Debugw("Retrieved logicalport from packet-in", log.Fields{"logicalPortNum": logicalPortNum, "IntfType": packetIn.IntfType})
1536 return logicalPortNum, nil
1537}
1538
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001539//GetPacketOutGemPortID returns gemPortId
1540func (f *OpenOltFlowMgr) GetPacketOutGemPortID(intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
1541 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001542 var err error
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001543 key := packetInInfoKey{intfID: intfID, onuID: onuID, logicalPort: portNum}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001544 if val, ok := f.packetInGemPort[key]; ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001545 gemPortID = val
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001546 } else {
1547 log.Errorw("Key-Error while fetching packet-out GEM port", log.Fields{"key": key})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001548 err = errors.New("key-error while fetching packet-out GEM port")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001549 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001550 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001551}
1552
Manikkaraj kb1d51442019-07-23 10:41:02 -04001553func installFlowOnAllGemports(
1554 f1 func(intfId uint32, onuId uint32, uniId uint32,
1555 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
1556 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32),
1557 f2 func(intfId uint32, onuId uint32, uniId uint32, portNo uint32,
1558 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32),
1559 args map[string]uint32,
1560 classifier map[string]interface{}, action map[string]interface{},
1561 logicalFlow *ofp.OfpFlowStats,
1562 gemPorts []uint32,
1563 FlowType string,
1564 vlanId ...uint32) {
1565 log.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanId})
1566 for _, gemPortId := range gemPorts {
1567 if FlowType == HsiaFlow || FlowType == DhcpFlow {
1568 f1(args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortId)
1569 } else if FlowType == EapolFlow {
1570 f2(args["intfId"], args["onuId"], args["uniId"], args["portNo"], logicalFlow, args["allocId"], gemPortId, vlanId[0])
1571 } else {
1572 log.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
1573 return
1574 }
1575 }
1576}
1577
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001578func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
1579 log.Debug("Adding trap-dhcp-of-nni-flow")
1580 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001581 classifier[PacketTagType] = DoubleTag
1582 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001583 /* We manage flowId resource pool on per PON port basis.
1584 Since this situation is tricky, as a hack, we pass the NNI port
1585 index (network_intf_id) as PON port Index for the flowId resource
1586 pool. Also, there is no ONU Id available for trapping DHCP packets
1587 on NNI port, use onu_id as -1 (invalid)
1588 ****************** CAVEAT *******************
1589 This logic works if the NNI Port Id falls within the same valid
1590 range of PON Port Ids. If this doesn't work for some OLT Vendor
1591 we need to have a re-look at this.
1592 *********************************************
1593 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001594 onuID := -1
1595 uniID := -1
1596 gemPortID := -1
1597 allocID := -1
1598 networkInterfaceID := f.deviceHandler.nniIntfID
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001599 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001600 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), flowStoreCookie); present {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001601 log.Debug("Flow-exists--not-re-adding")
1602 return
1603 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001604 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001605 if err != nil {
1606 log.Errorw("Flow id unavailable for DHCP traponNNI flow", log.Fields{"error": err})
1607 return
1608 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001609 var classifierProto *openoltpb2.Classifier
1610 var actionProto *openoltpb2.Action
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001611 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
1612 log.Error("Error in making classifier protobuf for dhcp trap on nni flow")
1613 return
1614 }
1615 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1616 if actionProto = makeOpenOltActionField(action); actionProto == nil {
1617 log.Error("Error in making action protobuf for dhcp trap on nni flow")
1618 return
1619 }
1620 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001621 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1622 OnuId: int32(onuID), // OnuId not required
1623 UniId: int32(uniID), // UniId not used
1624 FlowId: flowID,
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001625 FlowType: DOWNSTREAM,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001626 AllocId: int32(allocID), // AllocId not used
1627 NetworkIntfId: int32(networkInterfaceID),
1628 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001629 Classifier: classifierProto,
1630 Action: actionProto,
1631 Priority: int32(logicalFlow.Priority),
1632 Cookie: logicalFlow.Cookie,
1633 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001634 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001635 log.Debug("DHCP trap on NNI flow added to device successfully")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001636 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID)
1637 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1638 int32(onuID),
1639 int32(uniID),
1640 flowID, flowsToKVStore); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001641 log.Errorw("Error uploading DHCP DL flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1642 }
1643 }
1644 return
1645}