blob: 7baabb1bad88b472cff3ff452e13122d7400f69b [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"
serkant.uluderya245caba2019-09-24 23:15:29 -070032 "github.com/opencord/voltha-protos/go/common"
manikkaraj k17652a72019-05-06 09:06:36 -040033 ic "github.com/opencord/voltha-protos/go/inter_container"
manikkaraj kbf256be2019-03-25 00:13:48 +053034 ofp "github.com/opencord/voltha-protos/go/openflow_13"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070035 openoltpb2 "github.com/opencord/voltha-protos/go/openolt"
Manikkaraj kb1d51442019-07-23 10:41:02 -040036 tp_pb "github.com/opencord/voltha-protos/go/tech_profile"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070037 "github.com/opencord/voltha-protos/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040038
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -040039 //deepcopy "github.com/getlantern/deepcopy"
Daniele Rossi22db98e2019-07-11 11:50:00 +000040 "google.golang.org/grpc/codes"
41 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053042)
43
44const (
45 // Flow categories
manikkaraj kbf256be2019-03-25 00:13:48 +053046
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070047 //HsiaFlow flow category
48 HsiaFlow = "HSIA_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053049
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070050 //EapolFlow flow category
51 EapolFlow = "EAPOL_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053052
Manikkaraj kb1d51442019-07-23 10:41:02 -040053 //DhcpFlow flow category
54 DhcpFlow = "DHCP_FLOW"
55
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070056 //IPProtoDhcp flow category
57 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053058
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070059 //IPProtoIgmp flow category
60 IPProtoIgmp = 2
61
62 //EapEthType eapethtype value
63 EapEthType = 0x888e
64 //LldpEthType lldp ethtype value
65 LldpEthType = 0x88cc
66
67 //IgmpProto proto value
68 IgmpProto = 2
manikkaraj kbf256be2019-03-25 00:13:48 +053069
70 //FIXME - see also BRDCM_DEFAULT_VLAN in broadcom_onu.py
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070071
Humera Kouser94d7a842019-08-25 19:04:32 -040072 //ReservedVlan Transparent Vlan
David K. Bainbridge82efc492019-09-04 09:57:11 -070073 ReservedVlan = 4095
Harsh Awasthiea45af72019-08-26 02:39:00 -040074
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070075 //DefaultMgmtVlan default vlan value
76 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053077
manikkaraj kbf256be2019-03-25 00:13:48 +053078 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070079
David K. Bainbridge82efc492019-09-04 09:57:11 -070080 //Upstream constant
81 Upstream = "upstream"
82 //Downstream constant
83 Downstream = "downstream"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070084 //PacketTagType constant
85 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070086 //Untagged constant
87 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070088 //SingleTag constant
89 SingleTag = "single_tag"
90 //DoubleTag constant
91 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053092
93 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070094
95 //EthType constant
96 EthType = "eth_type"
97 //TPID constant
98 TPID = "tpid"
99 //IPProto constant
100 IPProto = "ip_proto"
101 //InPort constant
102 InPort = "in_port"
103 //VlanVid constant
104 VlanVid = "vlan_vid"
105 //VlanPcp constant
106 VlanPcp = "vlan_pcp"
107
108 //UDPDst constant
109 UDPDst = "udp_dst"
110 //UDPSrc constant
111 UDPSrc = "udp_src"
112 //Ipv4Dst constant
113 Ipv4Dst = "ipv4_dst"
114 //Ipv4Src constant
115 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700116 //Metadata constant
117 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700118 //TunnelID constant
119 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700120 //Output constant
121 Output = "output"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700122 // Actions
123
124 //PopVlan constant
125 PopVlan = "pop_vlan"
126 //PushVlan constant
127 PushVlan = "push_vlan"
128 //TrapToHost constant
129 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400130 //MaxMeterBand constant
131 MaxMeterBand = 2
132 //VlanPCPMask contant
133 VlanPCPMask = 0xFF
134 //VlanvIDMask constant
135 VlanvIDMask = 0xFFF
136 //MaxPonPorts constant
137 MaxPonPorts = 16
manikkaraj kbf256be2019-03-25 00:13:48 +0530138)
139
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400140type onuInfo struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700141 intfID uint32
142 onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400143 serialNumber string
144}
145
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700146type onuIDKey struct {
147 intfID uint32
148 onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400149}
150
151type gemPortKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700152 intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400153 gemPort uint32
154}
155
156type packetInInfoKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700157 intfID uint32
158 onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400159 logicalPort uint32
160}
161
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700162//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530163type OpenOltFlowMgr struct {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400164 techprofile []*tp.TechProfileMgr
165 deviceHandler *DeviceHandler
166 resourceMgr *rsrcMgr.OpenOltResourceMgr
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700167 onuIds map[onuIDKey]onuInfo //OnuId -> OnuInfo
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400168 onuSerialNumbers map[string]onuInfo //onu serial_number (string) -> OnuInfo
169 onuGemPortIds map[gemPortKey]onuInfo //GemPortId -> OnuInfo
170 packetInGemPort map[packetInInfoKey]uint32 //packet in gem port
171 storedDeviceFlows []ofp.OfpFlowStats /* Required during deletion to obtain device flows from logical flows */
manikkaraj kbf256be2019-03-25 00:13:48 +0530172}
173
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700174//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
manikkaraj kbf256be2019-03-25 00:13:48 +0530175func NewFlowManager(dh *DeviceHandler, rsrcMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
176 log.Info("Initializing flow manager")
177 var flowMgr OpenOltFlowMgr
178 flowMgr.deviceHandler = dh
179 flowMgr.resourceMgr = rsrcMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400180 flowMgr.techprofile = make([]*tp.TechProfileMgr, MaxPonPorts)
manikkaraj kbf256be2019-03-25 00:13:48 +0530181 if err := flowMgr.populateTechProfilePerPonPort(); err != nil {
182 log.Error("Error while populating tech profile mgr\n")
183 return nil
184 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700185 flowMgr.onuIds = make(map[onuIDKey]onuInfo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400186 flowMgr.onuSerialNumbers = make(map[string]onuInfo)
187 flowMgr.onuGemPortIds = make(map[gemPortKey]onuInfo)
188 flowMgr.packetInGemPort = make(map[packetInInfoKey]uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530189 log.Info("Initialization of flow manager success!!")
190 return &flowMgr
191}
192
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700193func (f *OpenOltFlowMgr) generateStoredFlowID(flowID uint32, direction string) (uint64, error) {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700194 if direction == Upstream {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400195 log.Debug("upstream flow, shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700196 return 0x1<<15 | uint64(flowID), nil
David K. Bainbridge82efc492019-09-04 09:57:11 -0700197 } else if direction == Downstream {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400198 log.Debug("downstream flow, not shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700199 return uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400200 } else {
201 log.Debug("Unrecognized direction")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700202 return 0, fmt.Errorf("unrecognized direction %s", direction)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400203 }
204}
205
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700206func (f *OpenOltFlowMgr) registerFlow(flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400207 log.Debug("Registering Flow for Device ", log.Fields{"flow": flowFromCore},
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700208 log.Fields{"device": f.deviceHandler.deviceID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400209
210 var storedFlow ofp.OfpFlowStats
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700211 storedFlow.Id, _ = f.generateStoredFlowID(deviceFlow.FlowId, deviceFlow.FlowType)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400212 log.Debug(fmt.Sprintf("Generated stored device flow. id = %d, flowId = %d, direction = %s", storedFlow.Id,
213 deviceFlow.FlowId, deviceFlow.FlowType))
214 storedFlow.Cookie = flowFromCore.Id
215 f.storedDeviceFlows = append(f.storedDeviceFlows, storedFlow)
216 log.Debugw("updated Stored flow info", log.Fields{"storedDeviceFlows": f.storedDeviceFlows})
217}
218
salmansiddiqui7ac62132019-08-22 03:58:50 +0000219func (f *OpenOltFlowMgr) divideAndAddFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32,
220 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
221 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) {
222 var allocID []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530223 var gemPorts []uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400224 var gemPort uint32
225 var TpInst *tp.TechProfile
manikkaraj kbf256be2019-03-25 00:13:48 +0530226
Manikkaraj kb1d51442019-07-23 10:41:02 -0400227 log.Infow("Dividing flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "portNo": portNo,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000228 "classifier": classifierInfo, "action": actionInfo, "UsMeterID": UsMeterID, "DsMeterID": DsMeterID, "TpID": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400229 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
230 // is because the flow is an NNI flow and there would be no onu resources associated with it
231 // TODO: properly deal with NNI flows
Manikkaraj kb1d51442019-07-23 10:41:02 -0400232 if onuID <= 0 {
Matt Jeanneret77199612019-07-26 18:08:35 -0400233 log.Errorw("No onu id for flow", log.Fields{"portNo": portNo, "classifer": classifierInfo, "action": actionInfo})
manikkaraj kbf256be2019-03-25 00:13:48 +0530234 return
235 }
236
Manikkaraj kb1d51442019-07-23 10:41:02 -0400237 uni := getUniPortPath(intfID, onuID, uniID)
238 log.Debugw("Uni port name", log.Fields{"uni": uni})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000239 allocID, gemPorts, TpInst = f.createTcontGemports(intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
240 if allocID == nil || gemPorts == nil || TpInst == nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400241 log.Error("alloc-id-gem-ports-tp-unavailable")
242 return
243 }
244
245 /* Flows can be added specific to gemport if p-bits are received.
246 * If no pbit mentioned then adding flows for all gemports
manikkaraj kbf256be2019-03-25 00:13:48 +0530247 */
Manikkaraj kb1d51442019-07-23 10:41:02 -0400248
249 args := make(map[string]uint32)
250 args["intfId"] = intfID
251 args["onuId"] = onuID
252 args["uniId"] = uniID
253 args["portNo"] = portNo
salmansiddiqui7ac62132019-08-22 03:58:50 +0000254 args["allocId"] = allocID[0]
Manikkaraj kb1d51442019-07-23 10:41:02 -0400255
salmansiddiqui7ac62132019-08-22 03:58:50 +0000256 f.checkAndAddFlow(args, classifierInfo, actionInfo, flow, gemPort, intfID, onuID, uniID, portNo, TpInst, allocID, gemPorts, TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530257}
258
salmansiddiqui7ac62132019-08-22 03:58:50 +0000259// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
260func (f *OpenOltFlowMgr) CreateSchedulerQueues(Dir tp_pb.Direction, IntfID uint32, OnuID uint32, UniID uint32, UniPort uint32, TpInst *tp.TechProfile, MeterID uint32, flowMetadata *voltha.FlowMetadata) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400261
salmansiddiqui7ac62132019-08-22 03:58:50 +0000262 log.Debugw("CreateSchedulerQueues", log.Fields{"Dir": Dir, "IntfID": IntfID, "OnuID": OnuID,
263 "UniID": UniID, "MeterID": MeterID, "TpInst": *TpInst, "flowMetadata": flowMetadata})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400264
salmansiddiqui7ac62132019-08-22 03:58:50 +0000265 Direction, err := verifyMeterIDAndGetDirection(MeterID, Dir)
266 if err != nil {
267 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400268 }
269
270 /* Lets make a simple assumption that if the meter-id is present on the KV store,
271 * then the scheduler and queues configuration is applied on the OLT device
272 * in the given direction.
273 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000274
Manikkaraj kb1d51442019-07-23 10:41:02 -0400275 var SchedCfg *tp_pb.SchedulerConfig
salmansiddiqui7ac62132019-08-22 03:58:50 +0000276 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(Direction, IntfID, OnuID, UniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400277 if err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000278 log.Error("Failed to get meter for intf %d, onuid %d, uniid %d", IntfID, OnuID, UniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400279 return err
280 }
281 if KvStoreMeter != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000282 if KvStoreMeter.MeterId == MeterID {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400283 log.Debug("Scheduler already created for upstream")
284 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400285 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000286 log.Errorw("Dynamic meter update not supported", log.Fields{"KvStoreMeterId": KvStoreMeter.MeterId, "MeterID-in-flow": MeterID})
287 return errors.New("invalid-meter-id-in-flow")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400288 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000289 log.Debugw("Meter-does-not-exist-Creating-new", log.Fields{"MeterID": MeterID, "Direction": Direction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400290 if Dir == tp_pb.Direction_UPSTREAM {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000291 SchedCfg = f.techprofile[IntfID].GetUsScheduler(TpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400292 } else if Dir == tp_pb.Direction_DOWNSTREAM {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000293 SchedCfg = f.techprofile[IntfID].GetDsScheduler(TpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400294 }
295 var meterConfig *ofp.OfpMeterConfig
296 if flowMetadata != nil {
297 for _, meter := range flowMetadata.Meters {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000298 if MeterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400299 meterConfig = meter
300 log.Debugw("Found-meter-config-from-flowmetadata", log.Fields{"meterConfig": meterConfig})
301 break
302 }
303 }
304 } else {
305 log.Error("Flow-metadata-is-not-present-in-flow")
306 }
307 if meterConfig == nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000308 log.Errorw("Could-not-get-meterbands-from-flowMetadata", log.Fields{"flowMetadata": flowMetadata, "MeterID": MeterID})
309 return errors.New("failed-to-get-meter-from-flowMetadata")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400310 } else if len(meterConfig.Bands) < MaxMeterBand {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000311 log.Errorw("Invalid-number-of-bands-in-meter", log.Fields{"Bands": meterConfig.Bands, "MeterID": MeterID})
312 return errors.New("invalid-number-of-bands-in-meter")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400313 }
314 cir := meterConfig.Bands[0].Rate
315 cbs := meterConfig.Bands[0].BurstSize
316 eir := meterConfig.Bands[1].Rate
317 ebs := meterConfig.Bands[1].BurstSize
318 pir := cir + eir
319 pbs := cbs + ebs
320 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
321
salmansiddiqui7ac62132019-08-22 03:58:50 +0000322 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[IntfID].GetTrafficScheduler(TpInst, SchedCfg, TrafficShaping)}
Manikkaraj kb1d51442019-07-23 10:41:02 -0400323
324 log.Debugw("Sending Traffic scheduler create to device", log.Fields{"Direction": Direction, "TrafficScheds": TrafficSched})
325 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
salmansiddiqui7ac62132019-08-22 03:58:50 +0000326 IntfId: IntfID, OnuId: OnuID,
327 UniId: UniID, PortNo: UniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400328 TrafficScheds: TrafficSched}); err != nil {
329 log.Errorw("Failed to create traffic schedulers", log.Fields{"error": err})
330 return err
331 }
332 // On receiving the CreateTrafficQueues request, the driver should create corresponding
333 // downstream queues.
salmansiddiqui7ac62132019-08-22 03:58:50 +0000334 trafficQueues := f.techprofile[IntfID].GetTrafficQueues(TpInst, Dir)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400335 log.Debugw("Sending Traffic Queues create to device", log.Fields{"Direction": Direction, "TrafficQueues": trafficQueues})
336 if _, err := f.deviceHandler.Client.CreateTrafficQueues(context.Background(),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000337 &tp_pb.TrafficQueues{IntfId: IntfID, OnuId: OnuID,
338 UniId: UniID, PortNo: UniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400339 TrafficQueues: trafficQueues}); err != nil {
340 log.Errorw("Failed to create traffic queues in device", log.Fields{"error": err})
341 return err
342 }
343
salmansiddiqui7ac62132019-08-22 03:58:50 +0000344 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400345 * store the meter id on the KV store, for further reference.
346 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000347 if err := f.resourceMgr.UpdateMeterIDForOnu(Direction, IntfID, OnuID, UniID, meterConfig); err != nil {
348 log.Error("Failed to update meter id for onu %d, meterid %d", OnuID, MeterID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400349 return err
350 }
351 log.Debugw("updated-meter-info into KV store successfully", log.Fields{"Direction": Direction,
352 "Meter": meterConfig})
353 return nil
354}
355
salmansiddiqui7ac62132019-08-22 03:58:50 +0000356// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
357func (f *OpenOltFlowMgr) RemoveSchedulerQueues(Dir tp_pb.Direction, IntfID uint32, OnuID uint32, UniID uint32, UniPort uint32, TpInst *tp.TechProfile) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400358
359 var Direction string
360 var SchedCfg *tp_pb.SchedulerConfig
361 var err error
salmansiddiqui7ac62132019-08-22 03:58:50 +0000362 log.Debugw("Removing schedulers and Queues in OLT", log.Fields{"Direction": Dir, "IntfID": IntfID, "OnuID": OnuID, "UniID": UniID, "UniPort": UniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400363 if Dir == tp_pb.Direction_UPSTREAM {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000364 SchedCfg = f.techprofile[IntfID].GetUsScheduler(TpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400365 Direction = "upstream"
366 } else if Dir == tp_pb.Direction_DOWNSTREAM {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000367 SchedCfg = f.techprofile[IntfID].GetDsScheduler(TpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400368 Direction = "downstream"
369 }
370
salmansiddiqui7ac62132019-08-22 03:58:50 +0000371 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(Direction, IntfID, OnuID, UniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400372 if err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000373 log.Errorf("Failed to get Meter for Onu %d", OnuID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400374 return err
375 }
376 if KVStoreMeter == nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000377 log.Debugw("No-meter-has-been-installed-yet", log.Fields{"direction": Direction, "IntfID": IntfID, "OnuID": OnuID, "UniID": UniID})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400378 return nil
379 }
380 cir := KVStoreMeter.Bands[0].Rate
381 cbs := KVStoreMeter.Bands[0].BurstSize
382 eir := KVStoreMeter.Bands[1].Rate
383 ebs := KVStoreMeter.Bands[1].BurstSize
384 pir := cir + eir
385 pbs := cbs + ebs
386
387 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
388
salmansiddiqui7ac62132019-08-22 03:58:50 +0000389 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[IntfID].GetTrafficScheduler(TpInst, SchedCfg, TrafficShaping)}
390 TrafficQueues := f.techprofile[IntfID].GetTrafficQueues(TpInst, Dir)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400391
392 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(context.Background(),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000393 &tp_pb.TrafficQueues{IntfId: IntfID, OnuId: OnuID,
394 UniId: UniID, PortNo: UniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400395 TrafficQueues: TrafficQueues}); err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000396 log.Errorw("Failed to remove traffic queues", log.Fields{"error": err})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400397 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400398 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000399 log.Debug("Removed traffic queues successfully")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400400 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
salmansiddiqui7ac62132019-08-22 03:58:50 +0000401 IntfId: IntfID, OnuId: OnuID,
402 UniId: UniID, PortNo: UniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400403 TrafficScheds: TrafficSched}); err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000404 log.Errorw("failed to remove traffic schedulers", log.Fields{"error": err})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400405 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400406 }
407
salmansiddiqui7ac62132019-08-22 03:58:50 +0000408 log.Debug("Removed traffic schedulers successfully")
409
410 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400411 * delete the meter id on the KV store.
412 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000413 err = f.resourceMgr.RemoveMeterIDForOnu(Direction, IntfID, OnuID, UniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400414 if err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000415 log.Errorf("Failed to remove meter for onu %d, meter id %d", OnuID, KVStoreMeter.MeterId)
416 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400417 }
418 log.Debugw("Removed-meter-from-KV-store successfully", log.Fields{"MeterId": KVStoreMeter.MeterId, "dir": Direction})
419 return err
420}
421
manikkaraj kbf256be2019-03-25 00:13:48 +0530422// This function allocates tconts and GEM ports for an ONU, currently one TCONT is supported per ONU
Manikkaraj kb1d51442019-07-23 10:41:02 -0400423func (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 +0530424 var allocID []uint32
425 var gemPortIDs []uint32
426 //If we already have allocated earlier for this onu, render them
salmansiddiqui7ac62132019-08-22 03:58:50 +0000427 if tcontID := f.resourceMgr.GetCurrentAllocIDForOnu(intfID, onuID, uniID); tcontID != 0 {
428 allocID = append(allocID, tcontID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530429 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700430 gemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400431
432 tpPath := f.getTPpath(intfID, uni, TpID)
433 // Check tech profile instance already exists for derived port name
salmansiddiqui7ac62132019-08-22 03:58:50 +0000434 techProfileInstance, err := f.techprofile[intfID].GetTPInstanceFromKVStore(TpID, tpPath)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400435 if err != nil { // This should not happen, something wrong in KV backend transaction
436 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": TpID, "path": tpPath})
437 return nil, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530438 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400439
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700440 log.Debug("Creating New TConts and Gem ports", log.Fields{"pon": intfID, "onu": onuID, "uni": uniID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530441
salmansiddiqui7ac62132019-08-22 03:58:50 +0000442 if techProfileInstance == nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530443 log.Info("Creating tech profile instance", log.Fields{"path": tpPath})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000444 techProfileInstance = f.techprofile[intfID].CreateTechProfInstance(TpID, uni, intfID)
445 if techProfileInstance == nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530446 log.Error("Tech-profile-instance-creation-failed")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400447 return nil, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530448 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000449 f.resourceMgr.UpdateTechProfileIDForOnu(intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530450 } else {
451 log.Debugw("Tech-profile-instance-already-exist-for-given port-name", log.Fields{"uni": uni})
452 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400453 if UsMeterID != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000454 if err := f.CreateSchedulerQueues(tp_pb.Direction_UPSTREAM, intfID, onuID, uniID, uniPort, techProfileInstance, UsMeterID, flowMetadata); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400455 log.Errorw("CreateSchedulerQueues Failed-upstream", log.Fields{"error": err, "meterID": UsMeterID})
456 return nil, nil, nil
457 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530458 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400459 if DsMeterID != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000460 if err := f.CreateSchedulerQueues(tp_pb.Direction_DOWNSTREAM, intfID, onuID, uniID, uniPort, techProfileInstance, DsMeterID, flowMetadata); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400461 log.Errorw("CreateSchedulerQueues Failed-downstream", log.Fields{"error": err, "meterID": DsMeterID})
462 return nil, nil, nil
463 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530464 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400465 if len(allocID) == 0 { // Created TCONT first time
salmansiddiqui7ac62132019-08-22 03:58:50 +0000466 allocID = append(allocID, techProfileInstance.UsScheduler.AllocID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400467 }
468 if len(gemPortIDs) == 0 { // Create GEM ports first time
salmansiddiqui7ac62132019-08-22 03:58:50 +0000469 for _, gem := range techProfileInstance.UpstreamGemPortAttributeList {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400470 gemPortIDs = append(gemPortIDs, gem.GemportID)
471 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530472 }
473 log.Debugw("Allocated Tcont and GEM ports", log.Fields{"allocID": allocID, "gemports": gemPortIDs})
474 // Send Tconts and GEM ports to KV store
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700475 f.storeTcontsGEMPortsIntoKVStore(intfID, onuID, uniID, allocID, gemPortIDs)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000476 return allocID, gemPortIDs, techProfileInstance
manikkaraj kbf256be2019-03-25 00:13:48 +0530477}
478
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700479func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530480
481 log.Debugw("Storing allocated Tconts and GEM ports into KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700482 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "allocID": allocID, "gemPortIDs": gemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530483 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700484 if err := f.resourceMgr.UpdateAllocIdsForOnu(intfID, onuID, uniID, allocID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530485 log.Error("Errow while uploading allocID to KV store")
486 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700487 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(intfID, onuID, uniID, gemPortIDs); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530488 log.Error("Errow while uploading GEMports to KV store")
489 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700490 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(gemPortIDs, intfID, onuID, uniID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530491 log.Error("Errow while uploading gemtopon map to KV store")
492 }
493 log.Debug("Stored tconts and GEM into KV store successfully")
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400494 for _, gemPort := range gemPortIDs {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700495 f.addGemPortToOnuInfoMap(intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400496 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530497}
498
499func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000500 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530501 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000502 for _, intfID := range techRange.IntfIds {
503 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400504 tpCount++
salmansiddiqui7ac62132019-08-22 03:58:50 +0000505 log.Debugw("Init tech profile done", log.Fields{"intfID": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530506 }
507 }
508 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400509 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530510 log.Errorw("Error while populating techprofile",
Manikkaraj kb1d51442019-07-23 10:41:02 -0400511 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000512 return errors.New("error while populating techprofile mgrs")
manikkaraj kbf256be2019-03-25 00:13:48 +0530513 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400514 log.Infow("Populated techprofile for ponports successfully",
515 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
manikkaraj kbf256be2019-03-25 00:13:48 +0530516 return nil
517}
518
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700519func (f *OpenOltFlowMgr) addUpstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530520 portNo uint32, uplinkClassifier map[string]interface{},
521 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700522 allocID uint32, gemportID uint32) {
523 uplinkClassifier[PacketTagType] = SingleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530524 log.Debugw("Adding upstream data flow", log.Fields{"uplinkClassifier": uplinkClassifier, "uplinkAction": uplinkAction})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700525 f.addHSIAFlow(intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700526 Upstream, logicalFlow, allocID, gemportID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530527 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530528}
529
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700530func (f *OpenOltFlowMgr) addDownstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530531 portNo uint32, downlinkClassifier map[string]interface{},
532 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700533 allocID uint32, gemportID uint32) {
534 downlinkClassifier[PacketTagType] = DoubleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530535 log.Debugw("Adding downstream data flow", log.Fields{"downlinkClassifier": downlinkClassifier,
536 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400537 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
538 if vlan, exists := downlinkClassifier[VlanVid]; exists {
539 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700540 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Manikkaraj kb1d51442019-07-23 10:41:02 -0400541 if uint32(metadata.(uint64)) == MkUniPortNum(intfID, onuID, uniID) {
542 log.Infow("Ignoring DL trap device flow from core", log.Fields{"flow": logicalFlow})
543 return
544 }
545 }
546 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530547 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400548
Manikkaraj k884c1242019-04-11 16:26:42 +0530549 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700550 downlinkAction[PopVlan] = true
551 downlinkAction[VlanVid] = downlinkClassifier[VlanVid]
552 f.addHSIAFlow(intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700553 Downstream, logicalFlow, allocID, gemportID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530554}
555
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700556func (f *OpenOltFlowMgr) addHSIAFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +0530557 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700558 allocID uint32, gemPortID uint32) {
Manikkaraj k884c1242019-04-11 16:26:42 +0530559 /* One of the OLT platform (Broadcom BAL) requires that symmetric
560 flows require the same flow_id to be used across UL and DL.
561 Since HSIA flow is the only symmetric flow currently, we need to
562 re-use the flow_id across both direction. The 'flow_category'
563 takes priority over flow_cookie to find any available HSIA_FLOW
564 id for the ONU.
565 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700566 log.Debugw("Adding HSIA flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "classifier": classifier,
567 "action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530568 "logicalFlow": *logicalFlow})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000569 var vlanPit uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400570 if _, ok := classifier[VlanPcp]; ok {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000571 vlanPit = classifier[VlanPcp].(uint32)
572 log.Debugw("Found pbit in the flow", log.Fields{"vlan_pit": vlanPit})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400573 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700574 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000575 flowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, HsiaFlow, vlanPit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530576 if err != nil {
577 log.Errorw("Flow id unavailable for HSIA flow", log.Fields{"direction": direction})
578 return
579 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700580 var classifierProto *openoltpb2.Classifier
581 var actionProto *openoltpb2.Action
Manikkaraj k884c1242019-04-11 16:26:42 +0530582 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
583 log.Error("Error in making classifier protobuf for hsia flow")
584 return
585 }
586 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
587 if actionProto = makeOpenOltActionField(action); actionProto == nil {
588 log.Errorw("Error in making action protobuf for hsia flow", log.Fields{"direction": direction})
589 return
590 }
591 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700592 networkIntfID := f.deviceHandler.nniIntfID
593 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
594 OnuId: int32(onuID),
595 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000596 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530597 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700598 AllocId: int32(allocID),
599 NetworkIntfId: int32(networkIntfID),
600 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530601 Classifier: classifierProto,
602 Action: actionProto,
603 Priority: int32(logicalFlow.Priority),
604 Cookie: logicalFlow.Cookie,
605 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400606 if ok := f.addFlowToDevice(logicalFlow, &flow); ok {
Manikkaraj k884c1242019-04-11 16:26:42 +0530607 log.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000608 flowsToKVStore := f.getUpdatedFlowInfo(&flow, flowStoreCookie, HsiaFlow, flowID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530609 if err := f.updateFlowInfoToKVStore(flow.AccessIntfId,
610 flow.OnuId,
611 flow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400612 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530613 log.Errorw("Error uploading HSIA flow into KV store", log.Fields{"flow": flow, "direction": direction, "error": err})
614 return
615 }
616 }
617}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700618func (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 +0530619
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700620 var dhcpFlow openoltpb2.Flow
621 var actionProto *openoltpb2.Action
622 var classifierProto *openoltpb2.Classifier
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530623
624 // Clear the action map
625 for k := range action {
626 delete(action, k)
627 }
628
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700629 action[TrapToHost] = true
630 classifier[UDPSrc] = uint32(68)
631 classifier[UDPDst] = uint32(67)
632 classifier[PacketTagType] = SingleTag
633 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530634
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700635 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530636
Manikkaraj kb1d51442019-07-23 10:41:02 -0400637 flowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, "", 0 /*classifier[VLAN_PCP].(uint32)*/)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530638
639 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700640 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530641 return
642 }
643
644 log.Debugw("Creating UL DHCP flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID})
645
646 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
647 log.Error("Error in making classifier protobuf for ul flow")
648 return
649 }
650 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
651 if actionProto = makeOpenOltActionField(action); actionProto == nil {
652 log.Error("Error in making action protobuf for ul flow")
653 return
654 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700655 networkIntfID := f.deviceHandler.nniIntfID
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530656
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700657 dhcpFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
658 OnuId: int32(onuID),
659 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530660 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700661 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700662 AllocId: int32(allocID),
663 NetworkIntfId: int32(networkIntfID),
664 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530665 Classifier: classifierProto,
666 Action: actionProto,
667 Priority: int32(logicalFlow.Priority),
668 Cookie: logicalFlow.Cookie,
669 PortNo: portNo}
670
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400671 if ok := f.addFlowToDevice(logicalFlow, &dhcpFlow); ok {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530672 log.Debug("DHCP UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400673 flowsToKVStore := f.getUpdatedFlowInfo(&dhcpFlow, flowStoreCookie, "DHCP", flowID)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530674 if err := f.updateFlowInfoToKVStore(dhcpFlow.AccessIntfId,
675 dhcpFlow.OnuId,
676 dhcpFlow.UniId,
677 dhcpFlow.FlowId, flowsToKVStore); err != nil {
678 log.Errorw("Error uploading DHCP UL flow into KV store", log.Fields{"flow": dhcpFlow, "error": err})
679 return
680 }
681 }
682
manikkaraj kbf256be2019-03-25 00:13:48 +0530683 return
684}
685
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700686// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
687func (f *OpenOltFlowMgr) addEAPOLFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, vlanID uint32) {
688 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 +0530689
690 uplinkClassifier := make(map[string]interface{})
691 uplinkAction := make(map[string]interface{})
692 downlinkClassifier := make(map[string]interface{})
693 downlinkAction := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700694 var upstreamFlow openoltpb2.Flow
695 var downstreamFlow openoltpb2.Flow
manikkaraj kbf256be2019-03-25 00:13:48 +0530696
697 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700698 uplinkClassifier[EthType] = uint32(EapEthType)
699 uplinkClassifier[PacketTagType] = SingleTag
700 uplinkClassifier[VlanVid] = vlanID
manikkaraj kbf256be2019-03-25 00:13:48 +0530701 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700702 uplinkAction[TrapToHost] = true
703 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530704 //Add Uplink EAPOL Flow
Manikkaraj kb1d51442019-07-23 10:41:02 -0400705 uplinkFlowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530706 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700707 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manikkaraj k884c1242019-04-11 16:26:42 +0530708 return
manikkaraj kbf256be2019-03-25 00:13:48 +0530709 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700710 var classifierProto *openoltpb2.Classifier
711 var actionProto *openoltpb2.Action
712 log.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530713
714 if classifierProto = makeOpenOltClassifierField(uplinkClassifier); classifierProto == nil {
715 log.Error("Error in making classifier protobuf for ul flow")
716 return
717 }
718 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
719 if actionProto = makeOpenOltActionField(uplinkAction); actionProto == nil {
720 log.Error("Error in making action protobuf for ul flow")
721 return
722 }
723 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700724 networkIntfID := f.deviceHandler.nniIntfID
725 upstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
726 OnuId: int32(onuID),
727 UniId: int32(uniID),
728 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700729 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700730 AllocId: int32(allocID),
731 NetworkIntfId: int32(networkIntfID),
732 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530733 Classifier: classifierProto,
734 Action: actionProto,
735 Priority: int32(logicalFlow.Priority),
736 Cookie: logicalFlow.Cookie,
737 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400738 if ok := f.addFlowToDevice(logicalFlow, &upstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530739 log.Debug("EAPOL UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400740 flowCategory := "EAPOL"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700741 flowsToKVStore := f.getUpdatedFlowInfo(&upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530742 if err := f.updateFlowInfoToKVStore(upstreamFlow.AccessIntfId,
743 upstreamFlow.OnuId,
744 upstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400745 upstreamFlow.FlowId,
746 /* lowCategory, */
747 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530748 log.Errorw("Error uploading EAPOL UL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
749 return
750 }
751 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400752 // Dummy Downstream flow due to BAL 2.6 limitation
753 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530754 /* Add Downstream EAPOL Flow, Only for first EAP flow (BAL
755 # requirement)
756 # On one of the platforms (Broadcom BAL), when same DL classifier
757 # vlan was used across multiple ONUs, eapol flow re-adds after
758 # flow delete (cases of onu reboot/disable) fails.
759 # In order to generate unique vlan, a combination of intf_id
760 # onu_id and uniId is used.
761 # uniId defaults to 0, so add 1 to it.
762 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700763 log.Debugw("Creating DL EAPOL flow with default vlan", log.Fields{"vlan": vlanID})
764 specialVlanDlFlow := 4090 - intfID*onuID*(uniID+1)
manikkaraj kbf256be2019-03-25 00:13:48 +0530765 // Assert that we do not generate invalid vlans under no condition
766 if specialVlanDlFlow <= 2 {
767 log.Fatalw("invalid-vlan-generated", log.Fields{"vlan": specialVlanDlFlow})
768 return
769 }
770 log.Debugw("specialVlanEAPOLDlFlow:", log.Fields{"dl_vlan": specialVlanDlFlow})
771 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700772 downlinkClassifier[PacketTagType] = SingleTag
Manikkaraj kb1d51442019-07-23 10:41:02 -0400773 downlinkClassifier[EthType] = uint32(EapEthType)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700774 downlinkClassifier[VlanVid] = uint32(specialVlanDlFlow)
manikkaraj kbf256be2019-03-25 00:13:48 +0530775 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700776 downlinkAction[PushVlan] = true
777 downlinkAction[VlanVid] = vlanID
778 flowStoreCookie := getFlowStoreCookie(downlinkClassifier, gemPortID)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000779 downlinkFlowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530780 if err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530781 log.Errorw("flowId unavailable for DL EAPOL",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700782 log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
manikkaraj kbf256be2019-03-25 00:13:48 +0530783 return
784 }
785 log.Debugw("Creating DL EAPOL flow",
salmansiddiqui7ac62132019-08-22 03:58:50 +0000786 log.Fields{"dl_classifier": downlinkClassifier, "dl_action": downlinkAction, "downlinkFlowID": downlinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530787 if classifierProto = makeOpenOltClassifierField(downlinkClassifier); classifierProto == nil {
788 log.Error("Error in making classifier protobuf for downlink flow")
789 return
790 }
791 if actionProto = makeOpenOltActionField(downlinkAction); actionProto == nil {
792 log.Error("Error in making action protobuf for dl flow")
793 return
794 }
795 // Downstream flow in grpc protobuf
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700796 downstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
797 OnuId: int32(onuID),
798 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000799 FlowId: downlinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700800 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700801 AllocId: int32(allocID),
802 NetworkIntfId: int32(networkIntfID),
803 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530804 Classifier: classifierProto,
805 Action: actionProto,
806 Priority: int32(logicalFlow.Priority),
807 Cookie: logicalFlow.Cookie,
808 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400809 if ok := f.addFlowToDevice(logicalFlow, &downstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530810 log.Debug("EAPOL DL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400811 flowCategory := ""
salmansiddiqui7ac62132019-08-22 03:58:50 +0000812 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamFlow, flowStoreCookie, flowCategory, downlinkFlowID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530813 if err := f.updateFlowInfoToKVStore(downstreamFlow.AccessIntfId,
814 downstreamFlow.OnuId,
815 downstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400816 downstreamFlow.FlowId,
817 /* flowCategory, */
818 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530819 log.Errorw("Error uploading EAPOL DL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
820 return
821 }
822 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530823 }
824 log.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
825}
826
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700827func makeOpenOltClassifierField(classifierInfo map[string]interface{}) *openoltpb2.Classifier {
828 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -0700829
830 classifier.EthType, _ = classifierInfo[EthType].(uint32)
831 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
832 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
833 vid := vlanID & VlanvIDMask
834 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -0400835 classifier.OVid = vid
836 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530837 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700838 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
839 vid := uint32(metadata)
840 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -0400841 classifier.IVid = vid
842 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530843 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700844 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400845 if vlanPcp == 0 {
846 classifier.OPbits = VlanPCPMask
847 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700848 classifier.OPbits = vlanPcp & VlanPCPMask
Manikkaraj kb1d51442019-07-23 10:41:02 -0400849 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530850 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700851 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
852 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
853 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
854 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
855 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
856 classifier.PktTagType = pktTagType
857
858 switch pktTagType {
859 case SingleTag:
860 case DoubleTag:
861 case Untagged:
862 default:
manikkaraj kbf256be2019-03-25 00:13:48 +0530863 log.Error("Invalid tag type in classifier") // should not hit
864 return nil
865 }
866 }
867 return &classifier
868}
869
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700870func makeOpenOltActionField(actionInfo map[string]interface{}) *openoltpb2.Action {
871 var actionCmd openoltpb2.ActionCmd
872 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +0530873 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700874 if _, ok := actionInfo[PopVlan]; ok {
875 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530876 action.Cmd.RemoveOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700877 } else if _, ok := actionInfo[PushVlan]; ok {
878 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530879 action.Cmd.AddOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700880 } else if _, ok := actionInfo[TrapToHost]; ok {
881 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +0530882 } else {
883 log.Errorw("Invalid-action-field", log.Fields{"action": actionInfo})
884 return nil
885 }
886 return &action
887}
888
Manikkaraj kb1d51442019-07-23 10:41:02 -0400889func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uni string, TpID uint32) string {
890 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530891}
892
Devmalya Paul495b94a2019-08-27 19:42:00 -0400893// DeleteTechProfileInstance removes the tech profile instance from persistent storage
894func (f *OpenOltFlowMgr) DeleteTechProfileInstance(intfID uint32, onuID uint32, uniID uint32, sn string) error {
895 tpID := f.resourceMgr.GetTechProfileIDForOnu(intfID, onuID, uniID)
896 uniPortName := fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
897 if err := f.techprofile[intfID].DeleteTechProfileInstance(tpID, uniPortName); err != nil {
898 log.Debugw("Failed-to-delete-tp-instance-from-kv-store", log.Fields{"tp-id": tpID, "uni-port-name": uniPortName})
899 return err
900 }
901 return nil
902}
903
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700904func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530905 if len(classifier) == 0 { // should never happen
906 log.Error("Invalid classfier object")
907 return 0
908 }
909 var jsonData []byte
910 var flowString string
911 var err error
912 // TODO: Do we need to marshall ??
913 if jsonData, err = json.Marshal(classifier); err != nil {
914 log.Error("Failed to encode classifier")
915 return 0
916 }
917 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700918 if gemPortID != 0 {
919 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +0530920 }
921 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700922 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +0530923 hash := big.NewInt(0)
924 hash.SetBytes(h.Sum(nil))
925 return hash.Uint64()
926}
927
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700928func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openoltpb2.Flow, flowStoreCookie uint64, flowCategory string, deviceFlowID uint32) *[]rsrcMgr.FlowInfo {
929 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
930 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400931 /* For flows which trap out of the NNI, the AccessIntfId is invalid
932 (set to -1). In such cases, we need to refer to the NetworkIntfId .
933 */
934 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700935 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400936 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700937 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400938 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700939 // Get existing flows matching flowid for given subscriber from KV store
940 existingFlows := f.resourceMgr.GetFlowIDInfo(intfID, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -0400941 if existingFlows != nil {
942 log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700943 //for _, f := range *existingFlows {
944 // flows = append(flows, f)
945 //}
946 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -0400947 }
948 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 +0530949 return &flows
950}
951
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400952//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
953// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
954// var intfId uint32
955// /* For flows which trap out of the NNI, the AccessIntfId is invalid
956// (set to -1). In such cases, we need to refer to the NetworkIntfId .
957// */
958// if flow.AccessIntfId != -1 {
959// intfId = uint32(flow.AccessIntfId)
960// } else {
961// intfId = uint32(flow.NetworkIntfId)
962// }
963// // Get existing flows matching flowid for given subscriber from KV store
964// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
965// if existingFlows != nil {
966// log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
967// for _, f := range *existingFlows {
968// flows = append(flows, f)
969// }
970// }
971// log.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
972// return &flows
973//}
974
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700975func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
manikkaraj k17652a72019-05-06 09:06:36 -0400976 log.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700977 if err := f.resourceMgr.UpdateFlowIDInfo(intfID, onuID, uniID, flowID, flows); err != nil {
manikkaraj k17652a72019-05-06 09:06:36 -0400978 log.Debug("Error while Storing flow into KV store")
979 return err
980 }
981 log.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +0530982 return nil
983}
984
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700985func (f *OpenOltFlowMgr) addFlowToDevice(logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) bool {
Daniele Rossi22db98e2019-07-11 11:50:00 +0000986
987 var intfID uint32
988 /* For flows which trap out of the NNI, the AccessIntfId is invalid
989 (set to -1). In such cases, we need to refer to the NetworkIntfId .
990 */
991 if deviceFlow.AccessIntfId != -1 {
992 intfID = uint32(deviceFlow.AccessIntfId)
993 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400994 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +0000995 intfID = uint32(deviceFlow.NetworkIntfId)
996 }
997
manikkaraj kbf256be2019-03-25 00:13:48 +0530998 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
999 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001000
1001 st, _ := status.FromError(err)
1002 if st.Code() == codes.AlreadyExists {
1003 log.Debug("Flow already exixts", log.Fields{"err": err, "deviceFlow": deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301004 return false
1005 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001006
1007 if err != nil {
1008 log.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": deviceFlow})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001009 f.resourceMgr.FreeFlowID(intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001010 return false
1011 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001012 log.Debugw("Flow added to device successfully ", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001013 f.registerFlow(logicalFlow, deviceFlow)
1014 return true
1015}
1016
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001017func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) bool {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001018 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1019 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1020 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001021 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
1022 log.Warnw("Can not remove flow from device since it's unreachable", log.Fields{"err": err, "deviceFlow": deviceFlow})
1023 //Assume the flow is removed
1024 return true
1025 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001026 log.Errorw("Failed to Remove flow from device", log.Fields{"err": err, "deviceFlow": deviceFlow})
1027 return false
serkant.uluderya245caba2019-09-24 23:15:29 -07001028
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001029 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001030 log.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301031 return true
1032}
1033
1034/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1035 //update core flows_proxy : flows_proxy.update('/', flows)
1036}
1037
1038func generateStoredId(flowId uint32, direction string)uint32{
1039
David K. Bainbridge82efc492019-09-04 09:57:11 -07001040 if direction == Upstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301041 log.Debug("Upstream flow shifting flowid")
1042 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001043 }else if direction == Downstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301044 log.Debug("Downstream flow not shifting flowid")
1045 return flowId
1046 }else{
1047 log.Errorw("Unrecognized direction",log.Fields{"direction": direction})
1048 return flowId
1049 }
1050}
1051
1052*/
1053
Humera Kouser94d7a842019-08-25 19:04:32 -04001054func (f *OpenOltFlowMgr) addLLDPFlow(flow *ofp.OfpFlowStats, portNo uint32) {
1055
1056 classifierInfo := make(map[string]interface{})
1057 actionInfo := make(map[string]interface{})
1058
1059 classifierInfo[EthType] = uint32(LldpEthType)
1060 classifierInfo[PacketTagType] = Untagged
1061 actionInfo[TrapToHost] = true
1062
1063 // LLDP flow is installed to trap LLDP packets on the NNI port.
1064 // We manage flow_id resource pool on per PON port basis.
1065 // Since this situation is tricky, as a hack, we pass the NNI port
1066 // index (network_intf_id) as PON port Index for the flow_id resource
1067 // pool. Also, there is no ONU Id available for trapping LLDP packets
1068 // on NNI port, use onu_id as -1 (invalid)
1069 // ****************** CAVEAT *******************
1070 // This logic works if the NNI Port Id falls within the same valid
1071 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1072 // we need to have a re-look at this.
1073 // *********************************************
1074
1075 var onuID = -1
1076 var uniID = -1
1077 var gemPortID = -1
1078
1079 var networkInterfaceID = IntfIDFromNniPortNum(portNo)
1080 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
1081 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), flowStoreCookie); present {
1082 log.Debug("Flow-exists--not-re-adding")
1083 return
1084 }
1085 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
1086
1087 if err != nil {
1088 log.Errorw("Flow id unavailable for LLDP traponNNI flow", log.Fields{"error": err})
1089 return
1090 }
1091 var classifierProto *openoltpb2.Classifier
1092 var actionProto *openoltpb2.Action
1093 if classifierProto = makeOpenOltClassifierField(classifierInfo); classifierProto == nil {
1094 log.Error("Error in making classifier protobuf for LLDP trap on nni flow")
1095 return
1096 }
1097 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1098 if actionProto = makeOpenOltActionField(actionInfo); actionProto == nil {
1099 log.Error("Error in making action protobuf for LLDP trap on nni flow")
1100 return
1101 }
1102 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
1103
1104 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1105 OnuId: int32(onuID), // OnuId not required
1106 UniId: int32(uniID), // UniId not used
1107 FlowId: flowID,
1108 FlowType: Downstream,
1109 NetworkIntfId: int32(networkInterfaceID),
1110 GemportId: int32(gemPortID),
1111 Classifier: classifierProto,
1112 Action: actionProto,
1113 Priority: int32(flow.Priority),
1114 Cookie: flow.Cookie,
1115 PortNo: portNo}
1116 if ok := f.addFlowToDevice(flow, &downstreamflow); ok {
1117 log.Debug("LLDP trap on NNI flow added to device successfully")
1118 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID)
1119 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1120 int32(onuID),
1121 int32(uniID),
1122 flowID, flowsToKVStore); err != nil {
1123 log.Errorw("Error uploading LLDP flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1124 }
1125 }
1126 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301127}
1128
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001129func getUniPortPath(intfID uint32, onuID uint32, uniID uint32) string {
1130 return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1131}
1132
1133//getOnuChildDevice to fetch onu
1134func (f *OpenOltFlowMgr) getOnuChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
1135 log.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
1136 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
1137 onuDevice := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301138 if onuDevice == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001139 log.Errorw("onu not found", log.Fields{"intfId": parentPortNo, "onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301140 return nil, errors.New("onu not found")
manikkaraj kbf256be2019-03-25 00:13:48 +05301141 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301142 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1143 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301144}
1145
1146func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001147 log.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301148 return nil
1149}
1150
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001151func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
1152 log.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301153}
1154
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001155func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001156 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001157 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001158 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001159 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001160}
1161
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001162func (f *OpenOltFlowMgr) clearFlowFromResourceManager(flow *ofp.OfpFlowStats, flowID uint32, flowDirection string) {
1163 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowID": flowID, "flowDirection": flowDirection, "flow": *flow})
Humera Kouser94d7a842019-08-25 19:04:32 -04001164 portNum, ponIntf, onuID, uniID, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001165 if err != nil {
1166 log.Error(err)
1167 return
1168 }
1169 log.Debugw("Extracted access info from flow to be deleted",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001170 log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001171
Humera Kouser94d7a842019-08-25 19:04:32 -04001172 if ethType == LldpEthType {
1173 var networkInterfaceID uint32
1174 var onuID = -1
1175 var uniID = -1
1176
1177 networkInterfaceID = IntfIDFromNniPortNum(inPort)
1178 f.resourceMgr.FreeFlowID(networkInterfaceID, int32(onuID), int32(uniID), flowID)
1179 return
1180 }
1181
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001182 flowsInfo := f.resourceMgr.GetFlowIDInfo(ponIntf, onuID, uniID, flowID)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001183 if flowsInfo == nil {
1184 log.Debugw("No FlowInfo found found in KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001185 log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001186 return
1187 }
1188 var updatedFlows []rsrcMgr.FlowInfo
1189
1190 for _, flow := range *flowsInfo {
1191 updatedFlows = append(updatedFlows, flow)
1192 }
1193
1194 for i, storedFlow := range updatedFlows {
1195 if flowDirection == storedFlow.Flow.FlowType {
1196 //Remove the Flow from FlowInfo
1197 log.Debugw("Removing flow to be deleted", log.Fields{"flow": storedFlow})
1198 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1199 break
1200 }
1201 }
1202
1203 if len(updatedFlows) >= 0 {
1204 // There are still flows referencing the same flow_id.
1205 // So the flow should not be freed yet.
1206 // For ex: Case of HSIA where same flow is shared
1207 // between DS and US.
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001208 f.updateFlowInfoToKVStore(int32(ponIntf), int32(onuID), int32(uniID), flowID, &updatedFlows)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001209 if len(updatedFlows) == 0 {
1210 log.Debugw("Releasing flow Id to resource manager", log.Fields{"ponIntf": ponIntf, "onuId": onuID, "uniId": uniID, "flowId": flowID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001211 f.resourceMgr.FreeFlowID(ponIntf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001212 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001213 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001214 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ponIntf, onuID, uniID)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001215 if len(flowIds) == 0 {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001216 log.Debugf("Flow count for subscriber %d is zero", onuID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001217 kvstoreTpID := f.resourceMgr.GetTechProfileIDForOnu(ponIntf, onuID, uniID)
1218 if kvstoreTpID == 0 {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001219 log.Warnw("Could-not-find-techprofile-tableid-for-uni", log.Fields{"ponIntf": ponIntf, "onuId": onuID, "uniId": uniID})
1220 return
1221 }
1222 uni := getUniPortPath(ponIntf, onuID, uniID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001223 tpPath := f.getTPpath(ponIntf, uni, kvstoreTpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001224 log.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001225 techprofileInst, err := f.techprofile[ponIntf].GetTPInstanceFromKVStore(kvstoreTpID, tpPath)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001226 if err != nil { // This should not happen, something wrong in KV backend transaction
1227 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": 20, "path": tpPath})
1228 return
1229 }
1230 if techprofileInst == nil {
1231 log.Errorw("Tech-profile-instance-does-not-exist-in-KV Store", log.Fields{"tpPath": tpPath})
1232 return
1233 }
1234
1235 f.RemoveSchedulerQueues(tp_pb.Direction_UPSTREAM, ponIntf, onuID, uniID, portNum, techprofileInst)
1236 f.RemoveSchedulerQueues(tp_pb.Direction_DOWNSTREAM, ponIntf, onuID, uniID, portNum, techprofileInst)
1237 } else {
1238 log.Debugf("Flow ids for subscriber", log.Fields{"onu": onuID, "flows": flowIds})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001239 }
1240}
1241
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001242//RemoveFlow removes the flow from the device
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001243func (f *OpenOltFlowMgr) RemoveFlow(flow *ofp.OfpFlowStats) {
1244 log.Debugw("Removing Flow", log.Fields{"flow": flow})
1245 var deviceFlowsToRemove []ofp.OfpFlowStats
1246 var deletedFlowsIdx []int
1247 for _, curFlow := range f.storedDeviceFlows {
1248 if curFlow.Cookie == flow.Id {
1249 log.Debugw("Found found matching flow-cookie", log.Fields{"curFlow": curFlow})
1250 deviceFlowsToRemove = append(deviceFlowsToRemove, curFlow)
1251 }
1252 }
1253 log.Debugw("Flows to be deleted", log.Fields{"deviceFlowsToRemove": deviceFlowsToRemove})
1254 for index, curFlow := range deviceFlowsToRemove {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001255 id, direction := f.decodeStoredID(curFlow.GetId())
1256 removeFlowMessage := openoltpb2.Flow{FlowId: uint32(id), FlowType: direction}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001257 if ok := f.removeFlowFromDevice(&removeFlowMessage); ok {
1258 log.Debug("Flow removed from device successfully")
1259 deletedFlowsIdx = append(deletedFlowsIdx, index)
1260 f.clearFlowFromResourceManager(flow, uint32(id), direction) //TODO: Take care of the limitations
1261 }
1262
1263 }
1264 // Can be done in separate go routine as it takes time ?
1265 for _, flowToRemove := range deletedFlowsIdx {
1266 for index, storedFlow := range f.storedDeviceFlows {
1267 if deviceFlowsToRemove[flowToRemove].Cookie == storedFlow.Cookie {
1268 log.Debugw("Removing flow from local Store", log.Fields{"flow": storedFlow})
1269 f.storedDeviceFlows = append(f.storedDeviceFlows[:index], f.storedDeviceFlows[index+1:]...)
1270 break
1271 }
1272 }
1273 }
1274 log.Debugw("Flows removed from the data store",
1275 log.Fields{"number_of_flows_removed": len(deviceFlowsToRemove), "updated_stored_flows": f.storedDeviceFlows})
1276 return
1277}
1278
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001279// AddFlow add flow to device
Manikkaraj kb1d51442019-07-23 10:41:02 -04001280func (f *OpenOltFlowMgr) AddFlow(flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001281 classifierInfo := make(map[string]interface{})
1282 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001283 var UsMeterID uint32
1284 var DsMeterID uint32
1285
1286 log.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001287 formulateClassifierInfoFromFlow(classifierInfo, flow)
1288
1289 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
1290 if err != nil {
1291 // Error logging is already done in the called function
1292 // So just return in case of error
1293 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301294 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001295
manikkaraj k17652a72019-05-06 09:06:36 -04001296 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00001297 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
1298 if err != nil {
1299 // error if any, already logged in the called function
1300 return
manikkaraj k17652a72019-05-06 09:06:36 -04001301 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001302
David K. Bainbridge82efc492019-09-04 09:57:11 -07001303 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[Output]})
1304 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
Humera Kouser94d7a842019-08-25 19:04:32 -04001305 if ethType, ok := classifierInfo[EthType]; ok {
1306 if ethType.(uint32) == LldpEthType {
1307 log.Info("Adding LLDP flow")
1308 f.addLLDPFlow(flow, portNo)
1309 return
1310 }
1311 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001312 if ipProto, ok := classifierInfo[IPProto]; ok {
1313 if ipProto.(uint32) == IPProtoDhcp {
1314 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001315 if udpSrc.(uint32) == uint32(67) {
1316 log.Debug("trap-dhcp-from-nni-flow")
1317 f.addDHCPTrapFlowOnNNI(flow, classifierInfo, portNo)
1318 return
1319 }
1320 }
1321 }
1322 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001323 /* Metadata 8 bytes:
1324 Most Significant 2 Bytes = Inner VLAN
1325 Next 2 Bytes = Tech Profile ID(TPID)
1326 Least Significant 4 Bytes = Port ID
David K. Bainbridge82efc492019-09-04 09:57:11 -07001327 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
Manikkaraj kb1d51442019-07-23 10:41:02 -04001328 subscriber related flows.
1329 */
1330 metadata := utils.GetMetadataFromWriteMetadataAction(flow)
1331 if metadata == 0 {
1332 log.Error("Metadata is not present in flow which is mandatory")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001333 return
1334 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001335 TpID := utils.GetTechProfileIDFromWriteMetaData(metadata)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001336 kvstoreTpID := f.resourceMgr.GetTechProfileIDForOnu(intfID, onuID, uniID)
1337 if kvstoreTpID == 0 {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001338 log.Debugf("tpid-not-present-in-kvstore, using tp id %d from flow metadata", TpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001339 } else if kvstoreTpID != uint32(TpID) {
1340 log.Error(" Tech-profile-updates-not-supported", log.Fields{"Tpid-in-flow": TpID, "kvstore-TpId": kvstoreTpID})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001341 return
1342 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001343 log.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001344 if IsUpstream(actionInfo[Output].(uint32)) {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001345 UsMeterID = utils.GetMeterIdFromFlow(flow)
1346 log.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
1347 } else {
1348 DsMeterID = utils.GetMeterIdFromFlow(flow)
1349 log.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
1350
1351 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001352 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001353}
1354
1355//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04001356func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001357
1358 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301359 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001360 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301361 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301362 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301363 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04001364
Manikkaraj kb1d51442019-07-23 10:41:02 -04001365 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001366 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
manikkaraj k17652a72019-05-06 09:06:36 -04001367 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
1368 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1369 tpDownloadMsg,
1370 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
1371 f.deviceHandler.deviceType,
1372 onuDevice.Type,
1373 onuDevice.Id,
1374 onuDevice.ProxyAddress.DeviceId, "")
1375 if sendErr != nil {
1376 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1377 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1378 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1379 return sendErr
1380 }
1381 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05301382 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301383}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001384
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001385//UpdateOnuInfo function adds onu info to cache
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001386func (f *OpenOltFlowMgr) UpdateOnuInfo(intfID uint32, onuID uint32, serialNum string) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001387 onu := onuInfo{intfID: intfID, onuID: onuID, serialNumber: serialNum}
1388 onuIDkey := onuIDKey{intfID: intfID, onuID: onuID}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001389 f.onuIds[onuIDkey] = onu
1390 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
1391}
1392
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001393//addGemPortToOnuInfoMap function stores adds GEMport to ONU map
1394func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(intfID uint32, onuID uint32, gemPort uint32) {
1395 onuIDkey := onuIDKey{intfID: intfID, onuID: onuID}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001396 if val, ok := f.onuIds[onuIDkey]; ok {
1397 onuInfo := val
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001398 gemportKey := gemPortKey{intfID: intfID, gemPort: gemPort}
1399 f.onuGemPortIds[gemportKey] = onuInfo
1400 log.Debugw("Cached Gemport to Onuinfo map", log.Fields{"GemPort": gemPort, "intfId": onuInfo.intfID, "onuId": onuInfo.onuID})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001401 return
1402 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001403 log.Errorw("OnuInfo not found", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001404}
1405
1406// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001407
1408//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
1409func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
1410 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 -04001411 if serialNumber != "" {
1412 if onuInfo, ok := f.onuSerialNumbers[serialNumber]; ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001413 return onuInfo.onuID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001414 }
1415 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001416 gemportKey := gemPortKey{intfID: intfID, gemPort: gemPortID}
1417 if onuInfo, ok := f.onuGemPortIds[gemportKey]; ok {
1418 log.Debugw("Retrieved onu info from access", log.Fields{"intfId": intfID, "gemPortId": gemPortID, "onuId": onuInfo.onuID})
1419 return onuInfo.onuID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001420 }
1421 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001422 log.Errorw("onuid is not found", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPort": gemPortID})
1423 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 -04001424}
1425
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001426//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
1427func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001428 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001429 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001430 var err error
1431
1432 if packetIn.IntfType == "pon" {
1433 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001434 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001435 log.Errorw("Unable to get ONU ID from GEM/PON port", log.Fields{"pon port": packetIn.IntfId, "gemport": packetIn.GemportId})
1436 return logicalPortNum, err
1437 }
1438 if packetIn.PortNo != 0 {
1439 logicalPortNum = packetIn.PortNo
1440 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001441 uniID := uint32(0) // FIXME - multi-uni support
1442 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001443 }
1444 // 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 -07001445 pktInkey := packetInInfoKey{intfID: packetIn.IntfId, onuID: onuID, logicalPort: logicalPortNum}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001446 f.packetInGemPort[pktInkey] = packetIn.GemportId
1447 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001448 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001449 }
1450 log.Debugw("Retrieved logicalport from packet-in", log.Fields{"logicalPortNum": logicalPortNum, "IntfType": packetIn.IntfType})
1451 return logicalPortNum, nil
1452}
1453
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001454//GetPacketOutGemPortID returns gemPortId
1455func (f *OpenOltFlowMgr) GetPacketOutGemPortID(intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
1456 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001457 var err error
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001458 key := packetInInfoKey{intfID: intfID, onuID: onuID, logicalPort: portNum}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001459 if val, ok := f.packetInGemPort[key]; ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001460 gemPortID = val
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001461 } else {
1462 log.Errorw("Key-Error while fetching packet-out GEM port", log.Fields{"key": key})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001463 err = errors.New("key-error while fetching packet-out GEM port")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001464 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001465 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001466}
1467
Manikkaraj kb1d51442019-07-23 10:41:02 -04001468func installFlowOnAllGemports(
1469 f1 func(intfId uint32, onuId uint32, uniId uint32,
1470 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
1471 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32),
1472 f2 func(intfId uint32, onuId uint32, uniId uint32, portNo uint32,
1473 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32),
1474 args map[string]uint32,
1475 classifier map[string]interface{}, action map[string]interface{},
1476 logicalFlow *ofp.OfpFlowStats,
1477 gemPorts []uint32,
1478 FlowType string,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001479 vlanID ...uint32) {
1480 log.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
1481 for _, gemPortID := range gemPorts {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001482 if FlowType == HsiaFlow || FlowType == DhcpFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001483 f1(args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001484 } else if FlowType == EapolFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001485 f2(args["intfId"], args["onuId"], args["uniId"], args["portNo"], logicalFlow, args["allocId"], gemPortID, vlanID[0])
Manikkaraj kb1d51442019-07-23 10:41:02 -04001486 } else {
1487 log.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
1488 return
1489 }
1490 }
1491}
1492
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001493func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
1494 log.Debug("Adding trap-dhcp-of-nni-flow")
1495 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001496 classifier[PacketTagType] = DoubleTag
1497 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001498 /* We manage flowId resource pool on per PON port basis.
1499 Since this situation is tricky, as a hack, we pass the NNI port
1500 index (network_intf_id) as PON port Index for the flowId resource
1501 pool. Also, there is no ONU Id available for trapping DHCP packets
1502 on NNI port, use onu_id as -1 (invalid)
1503 ****************** CAVEAT *******************
1504 This logic works if the NNI Port Id falls within the same valid
1505 range of PON Port Ids. If this doesn't work for some OLT Vendor
1506 we need to have a re-look at this.
1507 *********************************************
1508 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001509 onuID := -1
1510 uniID := -1
1511 gemPortID := -1
1512 allocID := -1
1513 networkInterfaceID := f.deviceHandler.nniIntfID
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001514 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001515 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), flowStoreCookie); present {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001516 log.Debug("Flow-exists--not-re-adding")
1517 return
1518 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001519 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001520 if err != nil {
1521 log.Errorw("Flow id unavailable for DHCP traponNNI flow", log.Fields{"error": err})
1522 return
1523 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001524 var classifierProto *openoltpb2.Classifier
1525 var actionProto *openoltpb2.Action
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001526 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
1527 log.Error("Error in making classifier protobuf for dhcp trap on nni flow")
1528 return
1529 }
1530 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1531 if actionProto = makeOpenOltActionField(action); actionProto == nil {
1532 log.Error("Error in making action protobuf for dhcp trap on nni flow")
1533 return
1534 }
1535 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001536 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1537 OnuId: int32(onuID), // OnuId not required
1538 UniId: int32(uniID), // UniId not used
1539 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001540 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001541 AllocId: int32(allocID), // AllocId not used
1542 NetworkIntfId: int32(networkInterfaceID),
1543 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001544 Classifier: classifierProto,
1545 Action: actionProto,
1546 Priority: int32(logicalFlow.Priority),
1547 Cookie: logicalFlow.Cookie,
1548 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001549 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001550 log.Debug("DHCP trap on NNI flow added to device successfully")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001551 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID)
1552 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1553 int32(onuID),
1554 int32(uniID),
1555 flowID, flowsToKVStore); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001556 log.Errorw("Error uploading DHCP DL flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1557 }
1558 }
1559 return
1560}
salmansiddiqui7ac62132019-08-22 03:58:50 +00001561
1562func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
1563 if MeterID == 0 { // This should never happen
1564 log.Error("Invalid meter id")
1565 return "", errors.New("invalid meter id")
1566 }
1567 if Dir == tp_pb.Direction_UPSTREAM {
1568 return "upstream", nil
1569 } else if Dir == tp_pb.Direction_DOWNSTREAM {
1570 return "downstream", nil
1571 }
1572 return "", nil
1573}
1574
1575func (f *OpenOltFlowMgr) checkAndAddFlow(args map[string]uint32, classifierInfo map[string]interface{},
1576 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, gemPort, intfID, onuID, uniID, portNo uint32,
1577 TpInst *tp.TechProfile, allocID []uint32, gemPorts []uint32, TpID uint32, uni string) {
1578 if ipProto, ok := classifierInfo[IPProto]; ok {
1579 if ipProto.(uint32) == IPProtoDhcp {
1580 log.Info("Adding DHCP flow")
1581 if pcp, ok := classifierInfo[VlanPcp]; ok {
1582 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1583 tp_pb.Direction_UPSTREAM,
1584 pcp.(uint32))
1585 //Adding DHCP upstream flow
1586 f.addDHCPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
1587 } else {
1588 //Adding DHCP upstream flow to all gemports
1589 installFlowOnAllGemports(f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, DhcpFlow)
1590 }
1591
1592 } else if ipProto == IgmpProto {
1593 log.Info("igmp flow add ignored, not implemented yet")
1594 return
1595 } else {
1596 log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
1597 return
1598 }
1599 } else if ethType, ok := classifierInfo[EthType]; ok {
1600 if ethType.(uint32) == EapEthType {
1601 log.Info("Adding EAPOL flow")
1602 var vlanID uint32
1603 if val, ok := classifierInfo[VlanVid]; ok {
1604 vlanID = (val.(uint32)) & VlanvIDMask
1605 } else {
1606 vlanID = DefaultMgmtVlan
1607 }
1608 if pcp, ok := classifierInfo[VlanPcp]; ok {
1609 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1610 tp_pb.Direction_UPSTREAM,
1611 pcp.(uint32))
1612
1613 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID[0], gemPort, vlanID)
1614 } else {
1615 installFlowOnAllGemports(nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, EapolFlow, vlanID)
1616 }
1617 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001618 } else if _, ok := actionInfo[PushVlan]; ok {
1619 log.Info("Adding upstream data rule")
1620 if pcp, ok := classifierInfo[VlanPcp]; ok {
1621 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1622 tp_pb.Direction_UPSTREAM,
1623 pcp.(uint32))
1624 //Adding HSIA upstream flow
1625 f.addUpstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
1626 } else {
1627 //Adding HSIA upstream flow to all gemports
1628 installFlowOnAllGemports(f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1629 }
1630 } else if _, ok := actionInfo[PopVlan]; ok {
1631 log.Info("Adding Downstream data rule")
1632 if pcp, ok := classifierInfo[VlanPcp]; ok {
1633 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05001634 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001635 pcp.(uint32))
1636 //Adding HSIA downstream flow
1637 f.addDownstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
1638 } else {
1639 //Adding HSIA downstream flow to all gemports
1640 installFlowOnAllGemports(f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1641 }
1642 } else {
1643 log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
1644 return
1645 }
1646 // Send Techprofile download event to child device in go routine as it takes time
1647 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, TpID)
1648}
1649
1650func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
1651 for _, field := range utils.GetOfbFields(flow) {
1652 if field.Type == utils.ETH_TYPE {
1653 classifierInfo[EthType] = field.GetEthType()
1654 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
1655 } else if field.Type == utils.IP_PROTO {
1656 classifierInfo[IPProto] = field.GetIpProto()
1657 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
1658 } else if field.Type == utils.IN_PORT {
1659 classifierInfo[InPort] = field.GetPort()
1660 log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
1661 } else if field.Type == utils.VLAN_VID {
1662 classifierInfo[VlanVid] = field.GetVlanVid()
1663 log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
1664 } else if field.Type == utils.VLAN_PCP {
1665 classifierInfo[VlanPcp] = field.GetVlanPcp()
1666 log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
1667 } else if field.Type == utils.UDP_DST {
1668 classifierInfo[UDPDst] = field.GetUdpDst()
1669 log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
1670 } else if field.Type == utils.UDP_SRC {
1671 classifierInfo[UDPSrc] = field.GetUdpSrc()
1672 log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
1673 } else if field.Type == utils.IPV4_DST {
1674 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
1675 log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
1676 } else if field.Type == utils.IPV4_SRC {
1677 classifierInfo[Ipv4Src] = field.GetIpv4Src()
1678 log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
1679 } else if field.Type == utils.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001680 classifierInfo[Metadata] = field.GetTableMetadata()
1681 log.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001682 } else if field.Type == utils.TUNNEL_ID {
1683 classifierInfo[TunnelID] = field.GetTunnelId()
1684 log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
1685 } else {
1686 log.Errorw("Un supported field type", log.Fields{"type": field.Type})
1687 return
1688 }
1689 }
1690}
1691
1692func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
1693 for _, action := range utils.GetActions(flow) {
1694 if action.Type == utils.OUTPUT {
1695 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001696 actionInfo[Output] = out.GetPort()
1697 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001698 } else {
1699 log.Error("Invalid output port in action")
1700 return errors.New("invalid output port in action")
1701 }
1702 } else if action.Type == utils.POP_VLAN {
1703 actionInfo[PopVlan] = true
1704 log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
1705 } else if action.Type == utils.PUSH_VLAN {
1706 if out := action.GetPush(); out != nil {
1707 if tpid := out.GetEthertype(); tpid != 0x8100 {
1708 log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
1709 } else {
1710 actionInfo[PushVlan] = true
1711 actionInfo[TPID] = tpid
1712 log.Debugw("action-type-push-vlan",
1713 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
1714 }
1715 }
1716 } else if action.Type == utils.SET_FIELD {
1717 if out := action.GetSetField(); out != nil {
1718 if field := out.GetField(); field != nil {
1719 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
1720 log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
1721 return errors.New("invalid openflow class")
1722 }
1723 /*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
1724 if ofbField := field.GetOfbField(); ofbField != nil {
1725 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
1726 if vlan := ofbField.GetVlanVid(); vlan != 0 {
1727 actionInfo[VlanVid] = vlan & 0xfff
1728 log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
1729 } else {
1730 log.Error("No Invalid vlan id in set vlan-vid action")
1731 }
1732 } else {
1733 log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
1734 }
1735 }
1736 }
1737 }
1738 } else {
1739 log.Errorw("Un supported action type", log.Fields{"type": action.Type})
1740 return errors.New("un supported action type")
1741 }
1742 }
1743 return nil
1744}
1745
1746func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001747 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001748 log.Debug("Controller bound trap flows, getting inport from tunnelid")
1749 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
1750 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
1751 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
1752 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07001753 log.Debugw("upstream pon-to-controller-flow,inport-in-tunnelid", log.Fields{"newInPort": classifierInfo[InPort].(uint32), "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001754 } else {
1755 log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1756 return errors.New("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1757 }
1758 }
1759 } else {
1760 log.Debug("Non-Controller flows, getting uniport from tunnelid")
1761 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07001762 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001763 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001764 actionInfo[Output] = uniPort
1765 log.Debugw("downstream-nni-to-pon-port-flow, outport-in-tunnelid", log.Fields{"newOutPort": actionInfo[Output].(uint32), "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001766 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001767 log.Debug("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid", log.Fields{"InPort": classifierInfo[InPort].(uint32), "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001768 return errors.New("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid")
1769 }
1770 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
1771 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
1772 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
1773 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07001774 log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[Output].(uint32),
1775 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001776 } else {
1777 log.Debug("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid", log.Fields{"InPort": classifierInfo[InPort].(uint32),
David K. Bainbridge82efc492019-09-04 09:57:11 -07001778 "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001779 return errors.New("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid")
1780 }
1781 }
1782 }
1783 return nil
1784}