blob: 258dc5fc3c9c6749fa54a5c9b40d8d041a1d9efc [file] [log] [blame]
manikkaraj kbf256be2019-03-25 00:13:48 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070017//Package adaptercore provides the utility for olt devices, flows and statistics
manikkaraj kbf256be2019-03-25 00:13:48 +053018package adaptercore
19
20import (
21 "context"
22 "crypto/md5"
23 "encoding/json"
24 "errors"
25 "fmt"
Manikkaraj kb1d51442019-07-23 10:41:02 -040026 "math/big"
27
manikkaraj kbf256be2019-03-25 00:13:48 +053028 "github.com/opencord/voltha-go/common/log"
29 tp "github.com/opencord/voltha-go/common/techprofile"
Matt Jeannereta93dbed2019-05-17 12:40:05 -040030 "github.com/opencord/voltha-go/rw_core/utils"
Manikkaraj k884c1242019-04-11 16:26:42 +053031 rsrcMgr "github.com/opencord/voltha-openolt-adapter/adaptercore/resourcemanager"
manikkaraj k17652a72019-05-06 09:06:36 -040032 ic "github.com/opencord/voltha-protos/go/inter_container"
manikkaraj kbf256be2019-03-25 00:13:48 +053033 ofp "github.com/opencord/voltha-protos/go/openflow_13"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070034 openoltpb2 "github.com/opencord/voltha-protos/go/openolt"
Manikkaraj kb1d51442019-07-23 10:41:02 -040035 tp_pb "github.com/opencord/voltha-protos/go/tech_profile"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070036 "github.com/opencord/voltha-protos/go/voltha"
Chaitrashree G S230040a2019-08-20 20:50:47 -040037
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -040038 //deepcopy "github.com/getlantern/deepcopy"
Daniele Rossi22db98e2019-07-11 11:50:00 +000039 "google.golang.org/grpc/codes"
40 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053041)
42
43const (
44 // Flow categories
manikkaraj kbf256be2019-03-25 00:13:48 +053045
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070046 //HsiaFlow flow category
47 HsiaFlow = "HSIA_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053048
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070049 //EapolFlow flow category
50 EapolFlow = "EAPOL_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053051
Manikkaraj kb1d51442019-07-23 10:41:02 -040052 //DhcpFlow flow category
53 DhcpFlow = "DHCP_FLOW"
54
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070055 //IPProtoDhcp flow category
56 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053057
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070058 //IPProtoIgmp flow category
59 IPProtoIgmp = 2
60
61 //EapEthType eapethtype value
62 EapEthType = 0x888e
63 //LldpEthType lldp ethtype value
64 LldpEthType = 0x88cc
65
66 //IgmpProto proto value
67 IgmpProto = 2
manikkaraj kbf256be2019-03-25 00:13:48 +053068
69 //FIXME - see also BRDCM_DEFAULT_VLAN in broadcom_onu.py
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070070
salmansiddiqui598eb8e2019-08-22 03:58:50 +000071 //ReservedVlan Transparent Vlan
72 ReservedVlan = 4095
Harsh Awasthie9644e02019-08-26 02:39:00 -040073
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070074 //DefaultMgmtVlan default vlan value
75 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053076
manikkaraj kbf256be2019-03-25 00:13:48 +053077 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070078
salmansiddiqui598eb8e2019-08-22 03:58:50 +000079 //Upstream constant
80 Upstream = "upstream"
81 //Downstream constant
82 Downstream = "downstream"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070083 //PacketTagType constant
84 PacketTagType = "pkt_tag_type"
salmansiddiqui598eb8e2019-08-22 03:58:50 +000085 //Untagged constant
86 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070087 //SingleTag constant
88 SingleTag = "single_tag"
89 //DoubleTag constant
90 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053091
92 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070093
94 //EthType constant
95 EthType = "eth_type"
96 //TPID constant
97 TPID = "tpid"
98 //IPProto constant
99 IPProto = "ip_proto"
100 //InPort constant
101 InPort = "in_port"
102 //VlanVid constant
103 VlanVid = "vlan_vid"
104 //VlanPcp constant
105 VlanPcp = "vlan_pcp"
106
107 //UDPDst constant
108 UDPDst = "udp_dst"
109 //UDPSrc constant
110 UDPSrc = "udp_src"
111 //Ipv4Dst constant
112 Ipv4Dst = "ipv4_dst"
113 //Ipv4Src constant
114 Ipv4Src = "ipv4_src"
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000115 //Metadata constant
116 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700117 //TunnelID constant
118 TunnelID = "tunnel_id"
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000119 //Output constant
120 Output = "output"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700121 // Actions
122
123 //PopVlan constant
124 PopVlan = "pop_vlan"
125 //PushVlan constant
126 PushVlan = "push_vlan"
127 //TrapToHost constant
128 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400129 //MaxMeterBand constant
130 MaxMeterBand = 2
131 //VlanPCPMask contant
132 VlanPCPMask = 0xFF
133 //VlanvIDMask constant
134 VlanvIDMask = 0xFFF
135 //MaxPonPorts constant
136 MaxPonPorts = 16
manikkaraj kbf256be2019-03-25 00:13:48 +0530137)
138
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400139type onuInfo struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700140 intfID uint32
141 onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400142 serialNumber string
143}
144
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700145type onuIDKey struct {
146 intfID uint32
147 onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400148}
149
150type gemPortKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700151 intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400152 gemPort uint32
153}
154
155type packetInInfoKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700156 intfID uint32
157 onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400158 logicalPort uint32
159}
160
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700161//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530162type OpenOltFlowMgr struct {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400163 techprofile []*tp.TechProfileMgr
164 deviceHandler *DeviceHandler
165 resourceMgr *rsrcMgr.OpenOltResourceMgr
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700166 onuIds map[onuIDKey]onuInfo //OnuId -> OnuInfo
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400167 onuSerialNumbers map[string]onuInfo //onu serial_number (string) -> OnuInfo
168 onuGemPortIds map[gemPortKey]onuInfo //GemPortId -> OnuInfo
169 packetInGemPort map[packetInInfoKey]uint32 //packet in gem port
170 storedDeviceFlows []ofp.OfpFlowStats /* Required during deletion to obtain device flows from logical flows */
manikkaraj kbf256be2019-03-25 00:13:48 +0530171}
172
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700173//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
manikkaraj kbf256be2019-03-25 00:13:48 +0530174func NewFlowManager(dh *DeviceHandler, rsrcMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
175 log.Info("Initializing flow manager")
176 var flowMgr OpenOltFlowMgr
177 flowMgr.deviceHandler = dh
178 flowMgr.resourceMgr = rsrcMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400179 flowMgr.techprofile = make([]*tp.TechProfileMgr, MaxPonPorts)
manikkaraj kbf256be2019-03-25 00:13:48 +0530180 if err := flowMgr.populateTechProfilePerPonPort(); err != nil {
181 log.Error("Error while populating tech profile mgr\n")
182 return nil
183 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700184 flowMgr.onuIds = make(map[onuIDKey]onuInfo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400185 flowMgr.onuSerialNumbers = make(map[string]onuInfo)
186 flowMgr.onuGemPortIds = make(map[gemPortKey]onuInfo)
187 flowMgr.packetInGemPort = make(map[packetInInfoKey]uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530188 log.Info("Initialization of flow manager success!!")
189 return &flowMgr
190}
191
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700192func (f *OpenOltFlowMgr) generateStoredFlowID(flowID uint32, direction string) (uint64, error) {
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000193 if direction == Upstream {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400194 log.Debug("upstream flow, shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700195 return 0x1<<15 | uint64(flowID), nil
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000196 } else if direction == Downstream {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400197 log.Debug("downstream flow, not shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700198 return uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400199 } else {
200 log.Debug("Unrecognized direction")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700201 return 0, fmt.Errorf("unrecognized direction %s", direction)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400202 }
203}
204
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700205func (f *OpenOltFlowMgr) registerFlow(flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400206 log.Debug("Registering Flow for Device ", log.Fields{"flow": flowFromCore},
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700207 log.Fields{"device": f.deviceHandler.deviceID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400208
209 var storedFlow ofp.OfpFlowStats
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700210 storedFlow.Id, _ = f.generateStoredFlowID(deviceFlow.FlowId, deviceFlow.FlowType)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400211 log.Debug(fmt.Sprintf("Generated stored device flow. id = %d, flowId = %d, direction = %s", storedFlow.Id,
212 deviceFlow.FlowId, deviceFlow.FlowType))
213 storedFlow.Cookie = flowFromCore.Id
214 f.storedDeviceFlows = append(f.storedDeviceFlows, storedFlow)
215 log.Debugw("updated Stored flow info", log.Fields{"storedDeviceFlows": f.storedDeviceFlows})
216}
217
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000218func (f *OpenOltFlowMgr) divideAndAddFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32,
219 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
220 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) {
221 var allocID []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530222 var gemPorts []uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400223 var gemPort uint32
224 var TpInst *tp.TechProfile
manikkaraj kbf256be2019-03-25 00:13:48 +0530225
Manikkaraj kb1d51442019-07-23 10:41:02 -0400226 log.Infow("Dividing flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "portNo": portNo,
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000227 "classifier": classifierInfo, "action": actionInfo, "UsMeterID": UsMeterID, "DsMeterID": DsMeterID, "TpID": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400228 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
229 // is because the flow is an NNI flow and there would be no onu resources associated with it
230 // TODO: properly deal with NNI flows
Manikkaraj kb1d51442019-07-23 10:41:02 -0400231 if onuID <= 0 {
Matt Jeanneret77199612019-07-26 18:08:35 -0400232 log.Errorw("No onu id for flow", log.Fields{"portNo": portNo, "classifer": classifierInfo, "action": actionInfo})
manikkaraj kbf256be2019-03-25 00:13:48 +0530233 return
234 }
235
Manikkaraj kb1d51442019-07-23 10:41:02 -0400236 uni := getUniPortPath(intfID, onuID, uniID)
237 log.Debugw("Uni port name", log.Fields{"uni": uni})
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000238 allocID, gemPorts, TpInst = f.createTcontGemports(intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
239 if allocID == nil || gemPorts == nil || TpInst == nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400240 log.Error("alloc-id-gem-ports-tp-unavailable")
241 return
242 }
243
244 /* Flows can be added specific to gemport if p-bits are received.
245 * If no pbit mentioned then adding flows for all gemports
manikkaraj kbf256be2019-03-25 00:13:48 +0530246 */
Manikkaraj kb1d51442019-07-23 10:41:02 -0400247
248 args := make(map[string]uint32)
249 args["intfId"] = intfID
250 args["onuId"] = onuID
251 args["uniId"] = uniID
252 args["portNo"] = portNo
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000253 args["allocId"] = allocID[0]
Manikkaraj kb1d51442019-07-23 10:41:02 -0400254
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000255 f.checkAndAddFlow(args, classifierInfo, actionInfo, flow, gemPort, intfID, onuID, uniID, portNo, TpInst, allocID, gemPorts, TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530256}
257
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000258// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
259func (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 -0400260
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000261 log.Debugw("CreateSchedulerQueues", log.Fields{"Dir": Dir, "IntfID": IntfID, "OnuID": OnuID,
262 "UniID": UniID, "MeterID": MeterID, "TpInst": *TpInst, "flowMetadata": flowMetadata})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400263
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000264 Direction, err := verifyMeterIDAndGetDirection(MeterID, Dir)
265 if err != nil {
266 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400267 }
268
269 /* Lets make a simple assumption that if the meter-id is present on the KV store,
270 * then the scheduler and queues configuration is applied on the OLT device
271 * in the given direction.
272 */
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000273
Manikkaraj kb1d51442019-07-23 10:41:02 -0400274 var SchedCfg *tp_pb.SchedulerConfig
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000275 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(Direction, IntfID, OnuID, UniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400276 if err != nil {
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000277 log.Error("Failed to get meter for intf %d, onuid %d, uniid %d", IntfID, OnuID, UniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400278 return err
279 }
280 if KvStoreMeter != nil {
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000281 if KvStoreMeter.MeterId == MeterID {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400282 log.Debug("Scheduler already created for upstream")
283 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400284 }
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000285 log.Errorw("Dynamic meter update not supported", log.Fields{"KvStoreMeterId": KvStoreMeter.MeterId, "MeterID-in-flow": MeterID})
286 return errors.New("invalid-meter-id-in-flow")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400287 }
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000288 log.Debugw("Meter-does-not-exist-Creating-new", log.Fields{"MeterID": MeterID, "Direction": Direction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400289 if Dir == tp_pb.Direction_UPSTREAM {
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000290 SchedCfg = f.techprofile[IntfID].GetUsScheduler(TpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400291 } else if Dir == tp_pb.Direction_DOWNSTREAM {
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000292 SchedCfg = f.techprofile[IntfID].GetDsScheduler(TpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400293 }
294 var meterConfig *ofp.OfpMeterConfig
295 if flowMetadata != nil {
296 for _, meter := range flowMetadata.Meters {
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000297 if MeterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400298 meterConfig = meter
299 log.Debugw("Found-meter-config-from-flowmetadata", log.Fields{"meterConfig": meterConfig})
300 break
301 }
302 }
303 } else {
304 log.Error("Flow-metadata-is-not-present-in-flow")
305 }
306 if meterConfig == nil {
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000307 log.Errorw("Could-not-get-meterbands-from-flowMetadata", log.Fields{"flowMetadata": flowMetadata, "MeterID": MeterID})
308 return errors.New("failed-to-get-meter-from-flowMetadata")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400309 } else if len(meterConfig.Bands) < MaxMeterBand {
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000310 log.Errorw("Invalid-number-of-bands-in-meter", log.Fields{"Bands": meterConfig.Bands, "MeterID": MeterID})
311 return errors.New("invalid-number-of-bands-in-meter")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400312 }
313 cir := meterConfig.Bands[0].Rate
314 cbs := meterConfig.Bands[0].BurstSize
315 eir := meterConfig.Bands[1].Rate
316 ebs := meterConfig.Bands[1].BurstSize
317 pir := cir + eir
318 pbs := cbs + ebs
319 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
320
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000321 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[IntfID].GetTrafficScheduler(TpInst, SchedCfg, TrafficShaping)}
Manikkaraj kb1d51442019-07-23 10:41:02 -0400322
323 log.Debugw("Sending Traffic scheduler create to device", log.Fields{"Direction": Direction, "TrafficScheds": TrafficSched})
324 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000325 IntfId: IntfID, OnuId: OnuID,
326 UniId: UniID, PortNo: UniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400327 TrafficScheds: TrafficSched}); err != nil {
328 log.Errorw("Failed to create traffic schedulers", log.Fields{"error": err})
329 return err
330 }
331 // On receiving the CreateTrafficQueues request, the driver should create corresponding
332 // downstream queues.
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000333 trafficQueues := f.techprofile[IntfID].GetTrafficQueues(TpInst, Dir)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400334 log.Debugw("Sending Traffic Queues create to device", log.Fields{"Direction": Direction, "TrafficQueues": trafficQueues})
335 if _, err := f.deviceHandler.Client.CreateTrafficQueues(context.Background(),
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000336 &tp_pb.TrafficQueues{IntfId: IntfID, OnuId: OnuID,
337 UniId: UniID, PortNo: UniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400338 TrafficQueues: trafficQueues}); err != nil {
339 log.Errorw("Failed to create traffic queues in device", log.Fields{"error": err})
340 return err
341 }
342
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000343 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400344 * store the meter id on the KV store, for further reference.
345 */
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000346 if err := f.resourceMgr.UpdateMeterIDForOnu(Direction, IntfID, OnuID, UniID, meterConfig); err != nil {
347 log.Error("Failed to update meter id for onu %d, meterid %d", OnuID, MeterID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400348 return err
349 }
350 log.Debugw("updated-meter-info into KV store successfully", log.Fields{"Direction": Direction,
351 "Meter": meterConfig})
352 return nil
353}
354
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000355// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
356func (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 -0400357
358 var Direction string
359 var SchedCfg *tp_pb.SchedulerConfig
360 var err error
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000361 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 -0400362 if Dir == tp_pb.Direction_UPSTREAM {
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000363 SchedCfg = f.techprofile[IntfID].GetUsScheduler(TpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400364 Direction = "upstream"
365 } else if Dir == tp_pb.Direction_DOWNSTREAM {
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000366 SchedCfg = f.techprofile[IntfID].GetDsScheduler(TpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400367 Direction = "downstream"
368 }
369
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000370 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(Direction, IntfID, OnuID, UniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400371 if err != nil {
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000372 log.Errorf("Failed to get Meter for Onu %d", OnuID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400373 return err
374 }
375 if KVStoreMeter == nil {
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000376 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 -0400377 return nil
378 }
379 cir := KVStoreMeter.Bands[0].Rate
380 cbs := KVStoreMeter.Bands[0].BurstSize
381 eir := KVStoreMeter.Bands[1].Rate
382 ebs := KVStoreMeter.Bands[1].BurstSize
383 pir := cir + eir
384 pbs := cbs + ebs
385
386 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
387
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000388 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[IntfID].GetTrafficScheduler(TpInst, SchedCfg, TrafficShaping)}
389 TrafficQueues := f.techprofile[IntfID].GetTrafficQueues(TpInst, Dir)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400390
391 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(context.Background(),
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000392 &tp_pb.TrafficQueues{IntfId: IntfID, OnuId: OnuID,
393 UniId: UniID, PortNo: UniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400394 TrafficQueues: TrafficQueues}); err != nil {
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000395 log.Errorw("Failed to remove traffic queues", log.Fields{"error": err})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400396 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400397 }
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000398 log.Debug("Removed traffic queues successfully")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400399 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000400 IntfId: IntfID, OnuId: OnuID,
401 UniId: UniID, PortNo: UniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400402 TrafficScheds: TrafficSched}); err != nil {
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000403 log.Errorw("failed to remove traffic schedulers", log.Fields{"error": err})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400404 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400405 }
406
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000407 log.Debug("Removed traffic schedulers successfully")
408
409 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400410 * delete the meter id on the KV store.
411 */
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000412 err = f.resourceMgr.RemoveMeterIDForOnu(Direction, IntfID, OnuID, UniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400413 if err != nil {
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000414 log.Errorf("Failed to remove meter for onu %d, meter id %d", OnuID, KVStoreMeter.MeterId)
415 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400416 }
417 log.Debugw("Removed-meter-from-KV-store successfully", log.Fields{"MeterId": KVStoreMeter.MeterId, "dir": Direction})
418 return err
419}
420
manikkaraj kbf256be2019-03-25 00:13:48 +0530421// This function allocates tconts and GEM ports for an ONU, currently one TCONT is supported per ONU
Manikkaraj kb1d51442019-07-23 10:41:02 -0400422func (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 +0530423 var allocID []uint32
424 var gemPortIDs []uint32
425 //If we already have allocated earlier for this onu, render them
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000426 if tcontID := f.resourceMgr.GetCurrentAllocIDForOnu(intfID, onuID, uniID); tcontID != 0 {
427 allocID = append(allocID, tcontID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530428 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700429 gemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400430
431 tpPath := f.getTPpath(intfID, uni, TpID)
432 // Check tech profile instance already exists for derived port name
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000433 techProfileInstance, err := f.techprofile[intfID].GetTPInstanceFromKVStore(TpID, tpPath)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400434 if err != nil { // This should not happen, something wrong in KV backend transaction
435 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": TpID, "path": tpPath})
436 return nil, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530437 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400438
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700439 log.Debug("Creating New TConts and Gem ports", log.Fields{"pon": intfID, "onu": onuID, "uni": uniID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530440
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000441 if techProfileInstance == nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530442 log.Info("Creating tech profile instance", log.Fields{"path": tpPath})
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000443 techProfileInstance = f.techprofile[intfID].CreateTechProfInstance(TpID, uni, intfID)
444 if techProfileInstance == nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530445 log.Error("Tech-profile-instance-creation-failed")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400446 return nil, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530447 }
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000448 f.resourceMgr.UpdateTechProfileIDForOnu(intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530449 } else {
450 log.Debugw("Tech-profile-instance-already-exist-for-given port-name", log.Fields{"uni": uni})
451 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400452 if UsMeterID != 0 {
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000453 if err := f.CreateSchedulerQueues(tp_pb.Direction_UPSTREAM, intfID, onuID, uniID, uniPort, techProfileInstance, UsMeterID, flowMetadata); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400454 log.Errorw("CreateSchedulerQueues Failed-upstream", log.Fields{"error": err, "meterID": UsMeterID})
455 return nil, nil, nil
456 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530457 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400458 if DsMeterID != 0 {
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000459 if err := f.CreateSchedulerQueues(tp_pb.Direction_DOWNSTREAM, intfID, onuID, uniID, uniPort, techProfileInstance, DsMeterID, flowMetadata); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400460 log.Errorw("CreateSchedulerQueues Failed-downstream", log.Fields{"error": err, "meterID": DsMeterID})
461 return nil, nil, nil
462 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530463 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400464 if len(allocID) == 0 { // Created TCONT first time
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000465 allocID = append(allocID, techProfileInstance.UsScheduler.AllocID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400466 }
467 if len(gemPortIDs) == 0 { // Create GEM ports first time
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000468 for _, gem := range techProfileInstance.UpstreamGemPortAttributeList {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400469 gemPortIDs = append(gemPortIDs, gem.GemportID)
470 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530471 }
472 log.Debugw("Allocated Tcont and GEM ports", log.Fields{"allocID": allocID, "gemports": gemPortIDs})
473 // Send Tconts and GEM ports to KV store
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700474 f.storeTcontsGEMPortsIntoKVStore(intfID, onuID, uniID, allocID, gemPortIDs)
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000475 return allocID, gemPortIDs, techProfileInstance
manikkaraj kbf256be2019-03-25 00:13:48 +0530476}
477
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700478func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530479
480 log.Debugw("Storing allocated Tconts and GEM ports into KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700481 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "allocID": allocID, "gemPortIDs": gemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530482 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700483 if err := f.resourceMgr.UpdateAllocIdsForOnu(intfID, onuID, uniID, allocID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530484 log.Error("Errow while uploading allocID to KV store")
485 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700486 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(intfID, onuID, uniID, gemPortIDs); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530487 log.Error("Errow while uploading GEMports to KV store")
488 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700489 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(gemPortIDs, intfID, onuID, uniID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530490 log.Error("Errow while uploading gemtopon map to KV store")
491 }
492 log.Debug("Stored tconts and GEM into KV store successfully")
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400493 for _, gemPort := range gemPortIDs {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700494 f.addGemPortToOnuInfoMap(intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400495 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530496}
497
498func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000499 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530500 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000501 for _, intfID := range techRange.IntfIds {
502 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400503 tpCount++
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000504 log.Debugw("Init tech profile done", log.Fields{"intfID": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530505 }
506 }
507 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400508 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530509 log.Errorw("Error while populating techprofile",
Manikkaraj kb1d51442019-07-23 10:41:02 -0400510 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000511 return errors.New("error while populating techprofile mgrs")
manikkaraj kbf256be2019-03-25 00:13:48 +0530512 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400513 log.Infow("Populated techprofile for ponports successfully",
514 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
manikkaraj kbf256be2019-03-25 00:13:48 +0530515 return nil
516}
517
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700518func (f *OpenOltFlowMgr) addUpstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530519 portNo uint32, uplinkClassifier map[string]interface{},
520 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700521 allocID uint32, gemportID uint32) {
522 uplinkClassifier[PacketTagType] = SingleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530523 log.Debugw("Adding upstream data flow", log.Fields{"uplinkClassifier": uplinkClassifier, "uplinkAction": uplinkAction})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700524 f.addHSIAFlow(intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000525 Upstream, logicalFlow, allocID, gemportID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530526 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530527}
528
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700529func (f *OpenOltFlowMgr) addDownstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530530 portNo uint32, downlinkClassifier map[string]interface{},
531 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700532 allocID uint32, gemportID uint32) {
533 downlinkClassifier[PacketTagType] = DoubleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530534 log.Debugw("Adding downstream data flow", log.Fields{"downlinkClassifier": downlinkClassifier,
535 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400536 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
537 if vlan, exists := downlinkClassifier[VlanVid]; exists {
538 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000539 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Manikkaraj kb1d51442019-07-23 10:41:02 -0400540 if uint32(metadata.(uint64)) == MkUniPortNum(intfID, onuID, uniID) {
541 log.Infow("Ignoring DL trap device flow from core", log.Fields{"flow": logicalFlow})
542 return
543 }
544 }
545 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530546 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400547
Manikkaraj k884c1242019-04-11 16:26:42 +0530548 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700549 downlinkAction[PopVlan] = true
550 downlinkAction[VlanVid] = downlinkClassifier[VlanVid]
551 f.addHSIAFlow(intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000552 Downstream, logicalFlow, allocID, gemportID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530553}
554
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700555func (f *OpenOltFlowMgr) addHSIAFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +0530556 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700557 allocID uint32, gemPortID uint32) {
Manikkaraj k884c1242019-04-11 16:26:42 +0530558 /* One of the OLT platform (Broadcom BAL) requires that symmetric
559 flows require the same flow_id to be used across UL and DL.
560 Since HSIA flow is the only symmetric flow currently, we need to
561 re-use the flow_id across both direction. The 'flow_category'
562 takes priority over flow_cookie to find any available HSIA_FLOW
563 id for the ONU.
564 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700565 log.Debugw("Adding HSIA flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "classifier": classifier,
566 "action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530567 "logicalFlow": *logicalFlow})
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000568 var vlanPit uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400569 if _, ok := classifier[VlanPcp]; ok {
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000570 vlanPit = classifier[VlanPcp].(uint32)
571 log.Debugw("Found pbit in the flow", log.Fields{"vlan_pit": vlanPit})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400572 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700573 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000574 flowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, HsiaFlow, vlanPit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530575 if err != nil {
576 log.Errorw("Flow id unavailable for HSIA flow", log.Fields{"direction": direction})
577 return
578 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700579 var classifierProto *openoltpb2.Classifier
580 var actionProto *openoltpb2.Action
Manikkaraj k884c1242019-04-11 16:26:42 +0530581 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
582 log.Error("Error in making classifier protobuf for hsia flow")
583 return
584 }
585 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
586 if actionProto = makeOpenOltActionField(action); actionProto == nil {
587 log.Errorw("Error in making action protobuf for hsia flow", log.Fields{"direction": direction})
588 return
589 }
590 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700591 networkIntfID := f.deviceHandler.nniIntfID
592 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
593 OnuId: int32(onuID),
594 UniId: int32(uniID),
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000595 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530596 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700597 AllocId: int32(allocID),
598 NetworkIntfId: int32(networkIntfID),
599 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530600 Classifier: classifierProto,
601 Action: actionProto,
602 Priority: int32(logicalFlow.Priority),
603 Cookie: logicalFlow.Cookie,
604 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400605 if ok := f.addFlowToDevice(logicalFlow, &flow); ok {
Manikkaraj k884c1242019-04-11 16:26:42 +0530606 log.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000607 flowsToKVStore := f.getUpdatedFlowInfo(&flow, flowStoreCookie, HsiaFlow, flowID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530608 if err := f.updateFlowInfoToKVStore(flow.AccessIntfId,
609 flow.OnuId,
610 flow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400611 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530612 log.Errorw("Error uploading HSIA flow into KV store", log.Fields{"flow": flow, "direction": direction, "error": err})
613 return
614 }
615 }
616}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700617func (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 +0530618
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700619 var dhcpFlow openoltpb2.Flow
620 var actionProto *openoltpb2.Action
621 var classifierProto *openoltpb2.Classifier
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530622
623 // Clear the action map
624 for k := range action {
625 delete(action, k)
626 }
627
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700628 action[TrapToHost] = true
629 classifier[UDPSrc] = uint32(68)
630 classifier[UDPDst] = uint32(67)
631 classifier[PacketTagType] = SingleTag
632 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530633
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700634 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530635
Manikkaraj kb1d51442019-07-23 10:41:02 -0400636 flowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, "", 0 /*classifier[VLAN_PCP].(uint32)*/)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530637
638 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700639 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530640 return
641 }
642
643 log.Debugw("Creating UL DHCP flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID})
644
645 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
646 log.Error("Error in making classifier protobuf for ul flow")
647 return
648 }
649 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
650 if actionProto = makeOpenOltActionField(action); actionProto == nil {
651 log.Error("Error in making action protobuf for ul flow")
652 return
653 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700654 networkIntfID := f.deviceHandler.nniIntfID
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530655
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700656 dhcpFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
657 OnuId: int32(onuID),
658 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530659 FlowId: flowID,
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000660 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700661 AllocId: int32(allocID),
662 NetworkIntfId: int32(networkIntfID),
663 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530664 Classifier: classifierProto,
665 Action: actionProto,
666 Priority: int32(logicalFlow.Priority),
667 Cookie: logicalFlow.Cookie,
668 PortNo: portNo}
669
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400670 if ok := f.addFlowToDevice(logicalFlow, &dhcpFlow); ok {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530671 log.Debug("DHCP UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400672 flowsToKVStore := f.getUpdatedFlowInfo(&dhcpFlow, flowStoreCookie, "DHCP", flowID)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530673 if err := f.updateFlowInfoToKVStore(dhcpFlow.AccessIntfId,
674 dhcpFlow.OnuId,
675 dhcpFlow.UniId,
676 dhcpFlow.FlowId, flowsToKVStore); err != nil {
677 log.Errorw("Error uploading DHCP UL flow into KV store", log.Fields{"flow": dhcpFlow, "error": err})
678 return
679 }
680 }
681
manikkaraj kbf256be2019-03-25 00:13:48 +0530682 return
683}
684
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700685// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
686func (f *OpenOltFlowMgr) addEAPOLFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, vlanID uint32) {
687 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 +0530688
689 uplinkClassifier := make(map[string]interface{})
690 uplinkAction := make(map[string]interface{})
691 downlinkClassifier := make(map[string]interface{})
692 downlinkAction := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700693 var upstreamFlow openoltpb2.Flow
694 var downstreamFlow openoltpb2.Flow
manikkaraj kbf256be2019-03-25 00:13:48 +0530695
696 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700697 uplinkClassifier[EthType] = uint32(EapEthType)
698 uplinkClassifier[PacketTagType] = SingleTag
699 uplinkClassifier[VlanVid] = vlanID
manikkaraj kbf256be2019-03-25 00:13:48 +0530700 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700701 uplinkAction[TrapToHost] = true
702 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530703 //Add Uplink EAPOL Flow
Manikkaraj kb1d51442019-07-23 10:41:02 -0400704 uplinkFlowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530705 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700706 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manikkaraj k884c1242019-04-11 16:26:42 +0530707 return
manikkaraj kbf256be2019-03-25 00:13:48 +0530708 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700709 var classifierProto *openoltpb2.Classifier
710 var actionProto *openoltpb2.Action
711 log.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530712
713 if classifierProto = makeOpenOltClassifierField(uplinkClassifier); classifierProto == nil {
714 log.Error("Error in making classifier protobuf for ul flow")
715 return
716 }
717 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
718 if actionProto = makeOpenOltActionField(uplinkAction); actionProto == nil {
719 log.Error("Error in making action protobuf for ul flow")
720 return
721 }
722 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700723 networkIntfID := f.deviceHandler.nniIntfID
724 upstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
725 OnuId: int32(onuID),
726 UniId: int32(uniID),
727 FlowId: uplinkFlowID,
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000728 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700729 AllocId: int32(allocID),
730 NetworkIntfId: int32(networkIntfID),
731 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530732 Classifier: classifierProto,
733 Action: actionProto,
734 Priority: int32(logicalFlow.Priority),
735 Cookie: logicalFlow.Cookie,
736 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400737 if ok := f.addFlowToDevice(logicalFlow, &upstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530738 log.Debug("EAPOL UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400739 flowCategory := "EAPOL"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700740 flowsToKVStore := f.getUpdatedFlowInfo(&upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530741 if err := f.updateFlowInfoToKVStore(upstreamFlow.AccessIntfId,
742 upstreamFlow.OnuId,
743 upstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400744 upstreamFlow.FlowId,
745 /* lowCategory, */
746 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530747 log.Errorw("Error uploading EAPOL UL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
748 return
749 }
750 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400751 // Dummy Downstream flow due to BAL 2.6 limitation
752 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530753 /* Add Downstream EAPOL Flow, Only for first EAP flow (BAL
754 # requirement)
755 # On one of the platforms (Broadcom BAL), when same DL classifier
756 # vlan was used across multiple ONUs, eapol flow re-adds after
757 # flow delete (cases of onu reboot/disable) fails.
758 # In order to generate unique vlan, a combination of intf_id
759 # onu_id and uniId is used.
760 # uniId defaults to 0, so add 1 to it.
761 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700762 log.Debugw("Creating DL EAPOL flow with default vlan", log.Fields{"vlan": vlanID})
763 specialVlanDlFlow := 4090 - intfID*onuID*(uniID+1)
manikkaraj kbf256be2019-03-25 00:13:48 +0530764 // Assert that we do not generate invalid vlans under no condition
765 if specialVlanDlFlow <= 2 {
766 log.Fatalw("invalid-vlan-generated", log.Fields{"vlan": specialVlanDlFlow})
767 return
768 }
769 log.Debugw("specialVlanEAPOLDlFlow:", log.Fields{"dl_vlan": specialVlanDlFlow})
770 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700771 downlinkClassifier[PacketTagType] = SingleTag
Manikkaraj kb1d51442019-07-23 10:41:02 -0400772 downlinkClassifier[EthType] = uint32(EapEthType)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700773 downlinkClassifier[VlanVid] = uint32(specialVlanDlFlow)
manikkaraj kbf256be2019-03-25 00:13:48 +0530774 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700775 downlinkAction[PushVlan] = true
776 downlinkAction[VlanVid] = vlanID
777 flowStoreCookie := getFlowStoreCookie(downlinkClassifier, gemPortID)
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000778 downlinkFlowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530779 if err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530780 log.Errorw("flowId unavailable for DL EAPOL",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700781 log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
manikkaraj kbf256be2019-03-25 00:13:48 +0530782 return
783 }
784 log.Debugw("Creating DL EAPOL flow",
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000785 log.Fields{"dl_classifier": downlinkClassifier, "dl_action": downlinkAction, "downlinkFlowID": downlinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530786 if classifierProto = makeOpenOltClassifierField(downlinkClassifier); classifierProto == nil {
787 log.Error("Error in making classifier protobuf for downlink flow")
788 return
789 }
790 if actionProto = makeOpenOltActionField(downlinkAction); actionProto == nil {
791 log.Error("Error in making action protobuf for dl flow")
792 return
793 }
794 // Downstream flow in grpc protobuf
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700795 downstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
796 OnuId: int32(onuID),
797 UniId: int32(uniID),
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000798 FlowId: downlinkFlowID,
799 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700800 AllocId: int32(allocID),
801 NetworkIntfId: int32(networkIntfID),
802 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530803 Classifier: classifierProto,
804 Action: actionProto,
805 Priority: int32(logicalFlow.Priority),
806 Cookie: logicalFlow.Cookie,
807 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400808 if ok := f.addFlowToDevice(logicalFlow, &downstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530809 log.Debug("EAPOL DL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400810 flowCategory := ""
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000811 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamFlow, flowStoreCookie, flowCategory, downlinkFlowID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530812 if err := f.updateFlowInfoToKVStore(downstreamFlow.AccessIntfId,
813 downstreamFlow.OnuId,
814 downstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400815 downstreamFlow.FlowId,
816 /* flowCategory, */
817 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530818 log.Errorw("Error uploading EAPOL DL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
819 return
820 }
821 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530822 }
823 log.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
824}
825
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700826func makeOpenOltClassifierField(classifierInfo map[string]interface{}) *openoltpb2.Classifier {
827 var classifier openoltpb2.Classifier
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000828
829 classifier.EthType, _ = classifierInfo[EthType].(uint32)
830 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700831 if vlanID, ok := classifierInfo[VlanVid]; ok {
Harsh Awasthie9644e02019-08-26 02:39:00 -0400832 vid := (vlanID.(uint32)) & VlanvIDMask
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000833 if vid != ReservedVlan {
Harsh Awasthie9644e02019-08-26 02:39:00 -0400834 classifier.OVid = vid
835 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530836 }
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000837 if metadata, ok := classifierInfo[Metadata]; ok {
Harsh Awasthie9644e02019-08-26 02:39:00 -0400838 vid := uint32(metadata.(uint64))
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000839 if vid != ReservedVlan {
Harsh Awasthie9644e02019-08-26 02:39:00 -0400840 classifier.IVid = vid
841 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530842 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700843 if vlanPcp, ok := classifierInfo[VlanPcp]; ok {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400844 if vlanPcp == 0 {
845 classifier.OPbits = VlanPCPMask
846 } else {
847 classifier.OPbits = (vlanPcp.(uint32)) & VlanPCPMask
848 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530849 }
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000850 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
851 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
852 classifierInfo[Ipv4Dst], _ = classifierInfo[Ipv4Dst].(uint32)
853 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700854 if pktTagType, ok := classifierInfo[PacketTagType]; ok {
855 if pktTagType.(string) == SingleTag {
856 classifier.PktTagType = SingleTag
857 } else if pktTagType.(string) == DoubleTag {
858 classifier.PktTagType = DoubleTag
salmansiddiqui598eb8e2019-08-22 03:58:50 +0000859 } else if pktTagType.(string) == Untagged {
860 classifier.PktTagType = Untagged
manikkaraj kbf256be2019-03-25 00:13:48 +0530861 } else {
862 log.Error("Invalid tag type in classifier") // should not hit
863 return nil
864 }
865 }
866 return &classifier
867}
868
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700869func makeOpenOltActionField(actionInfo map[string]interface{}) *openoltpb2.Action {
870 var actionCmd openoltpb2.ActionCmd
871 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +0530872 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700873 if _, ok := actionInfo[PopVlan]; ok {
874 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530875 action.Cmd.RemoveOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700876 } else if _, ok := actionInfo[PushVlan]; ok {
877 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530878 action.Cmd.AddOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700879 } else if _, ok := actionInfo[TrapToHost]; ok {
880 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +0530881 } else {
882 log.Errorw("Invalid-action-field", log.Fields{"action": actionInfo})
883 return nil
884 }
885 return &action
886}
887
Manikkaraj kb1d51442019-07-23 10:41:02 -0400888func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uni string, TpID uint32) string {
889 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530890}
891
Devmalya Pauleb2e9552019-08-27 19:42:00 -0400892// DeleteTechProfileInstance removes the tech profile instance from persistent storage
893func (f *OpenOltFlowMgr) DeleteTechProfileInstance(intfID uint32, onuID uint32, uniID uint32, sn string) error {
894 tpID := f.resourceMgr.GetTechProfileIDForOnu(intfID, onuID, uniID)
895 uniPortName := fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
896 if err := f.techprofile[intfID].DeleteTechProfileInstance(tpID, uniPortName); err != nil {
897 log.Debugw("Failed-to-delete-tp-instance-from-kv-store", log.Fields{"tp-id": tpID, "uni-port-name": uniPortName})
898 return err
899 }
900 return nil
901}
902
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700903func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530904 if len(classifier) == 0 { // should never happen
905 log.Error("Invalid classfier object")
906 return 0
907 }
908 var jsonData []byte
909 var flowString string
910 var err error
911 // TODO: Do we need to marshall ??
912 if jsonData, err = json.Marshal(classifier); err != nil {
913 log.Error("Failed to encode classifier")
914 return 0
915 }
916 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700917 if gemPortID != 0 {
918 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +0530919 }
920 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700921 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +0530922 hash := big.NewInt(0)
923 hash.SetBytes(h.Sum(nil))
924 return hash.Uint64()
925}
926
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700927func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openoltpb2.Flow, flowStoreCookie uint64, flowCategory string, deviceFlowID uint32) *[]rsrcMgr.FlowInfo {
928 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
929 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400930 /* For flows which trap out of the NNI, the AccessIntfId is invalid
931 (set to -1). In such cases, we need to refer to the NetworkIntfId .
932 */
933 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700934 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400935 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700936 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400937 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700938 // Get existing flows matching flowid for given subscriber from KV store
939 existingFlows := f.resourceMgr.GetFlowIDInfo(intfID, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -0400940 if existingFlows != nil {
941 log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700942 //for _, f := range *existingFlows {
943 // flows = append(flows, f)
944 //}
945 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -0400946 }
947 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 +0530948 return &flows
949}
950
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400951//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
952// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
953// var intfId uint32
954// /* For flows which trap out of the NNI, the AccessIntfId is invalid
955// (set to -1). In such cases, we need to refer to the NetworkIntfId .
956// */
957// if flow.AccessIntfId != -1 {
958// intfId = uint32(flow.AccessIntfId)
959// } else {
960// intfId = uint32(flow.NetworkIntfId)
961// }
962// // Get existing flows matching flowid for given subscriber from KV store
963// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
964// if existingFlows != nil {
965// log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
966// for _, f := range *existingFlows {
967// flows = append(flows, f)
968// }
969// }
970// log.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
971// return &flows
972//}
973
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700974func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
manikkaraj k17652a72019-05-06 09:06:36 -0400975 log.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700976 if err := f.resourceMgr.UpdateFlowIDInfo(intfID, onuID, uniID, flowID, flows); err != nil {
manikkaraj k17652a72019-05-06 09:06:36 -0400977 log.Debug("Error while Storing flow into KV store")
978 return err
979 }
980 log.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +0530981 return nil
982}
983
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700984func (f *OpenOltFlowMgr) addFlowToDevice(logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) bool {
Daniele Rossi22db98e2019-07-11 11:50:00 +0000985
986 var intfID uint32
987 /* For flows which trap out of the NNI, the AccessIntfId is invalid
988 (set to -1). In such cases, we need to refer to the NetworkIntfId .
989 */
990 if deviceFlow.AccessIntfId != -1 {
991 intfID = uint32(deviceFlow.AccessIntfId)
992 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400993 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +0000994 intfID = uint32(deviceFlow.NetworkIntfId)
995 }
996
manikkaraj kbf256be2019-03-25 00:13:48 +0530997 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
998 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +0000999
1000 st, _ := status.FromError(err)
1001 if st.Code() == codes.AlreadyExists {
1002 log.Debug("Flow already exixts", log.Fields{"err": err, "deviceFlow": deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301003 return false
1004 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001005
1006 if err != nil {
1007 log.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": deviceFlow})
Devmalya Pauleb2e9552019-08-27 19:42:00 -04001008 f.resourceMgr.FreeFlowID(intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001009 return false
1010 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001011 log.Debugw("Flow added to device successfully ", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001012 f.registerFlow(logicalFlow, deviceFlow)
1013 return true
1014}
1015
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001016func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) bool {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001017 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1018 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1019 if err != nil {
1020 log.Errorw("Failed to Remove flow from device", log.Fields{"err": err, "deviceFlow": deviceFlow})
1021 return false
1022 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001023 log.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301024 return true
1025}
1026
1027/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1028 //update core flows_proxy : flows_proxy.update('/', flows)
1029}
1030
1031func generateStoredId(flowId uint32, direction string)uint32{
1032
salmansiddiqui598eb8e2019-08-22 03:58:50 +00001033 if direction == Upstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301034 log.Debug("Upstream flow shifting flowid")
1035 return ((0x1 << 15) | flowId)
salmansiddiqui598eb8e2019-08-22 03:58:50 +00001036 }else if direction == Downstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301037 log.Debug("Downstream flow not shifting flowid")
1038 return flowId
1039 }else{
1040 log.Errorw("Unrecognized direction",log.Fields{"direction": direction})
1041 return flowId
1042 }
1043}
1044
1045*/
1046
1047func addLLDPFlow(flow *ofp.OfpFlowStats, portNo uint32) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001048 log.Info("unimplemented flow : %v, portNo : %v ", flow, portNo)
manikkaraj kbf256be2019-03-25 00:13:48 +05301049}
1050
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001051func getUniPortPath(intfID uint32, onuID uint32, uniID uint32) string {
1052 return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1053}
1054
1055//getOnuChildDevice to fetch onu
1056func (f *OpenOltFlowMgr) getOnuChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
1057 log.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
1058 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
1059 onuDevice := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301060 if onuDevice == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001061 log.Errorw("onu not found", log.Fields{"intfId": parentPortNo, "onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301062 return nil, errors.New("onu not found")
manikkaraj kbf256be2019-03-25 00:13:48 +05301063 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301064 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1065 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301066}
1067
1068func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001069 log.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301070 return nil
1071}
1072
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001073func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
1074 log.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301075}
1076
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001077func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001078 if id>>15 == 0x1 {
salmansiddiqui598eb8e2019-08-22 03:58:50 +00001079 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001080 }
salmansiddiqui598eb8e2019-08-22 03:58:50 +00001081 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001082}
1083
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001084func (f *OpenOltFlowMgr) clearFlowFromResourceManager(flow *ofp.OfpFlowStats, flowID uint32, flowDirection string) {
1085 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowID": flowID, "flowDirection": flowDirection, "flow": *flow})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001086 portNum, ponIntf, onuID, uniID, err := FlowExtractInfo(flow, flowDirection)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001087 if err != nil {
1088 log.Error(err)
1089 return
1090 }
1091 log.Debugw("Extracted access info from flow to be deleted",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001092 log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001093
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001094 flowsInfo := f.resourceMgr.GetFlowIDInfo(ponIntf, onuID, uniID, flowID)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001095 if flowsInfo == nil {
1096 log.Debugw("No FlowInfo found found in KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001097 log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001098 return
1099 }
1100 var updatedFlows []rsrcMgr.FlowInfo
1101
1102 for _, flow := range *flowsInfo {
1103 updatedFlows = append(updatedFlows, flow)
1104 }
1105
1106 for i, storedFlow := range updatedFlows {
1107 if flowDirection == storedFlow.Flow.FlowType {
1108 //Remove the Flow from FlowInfo
1109 log.Debugw("Removing flow to be deleted", log.Fields{"flow": storedFlow})
1110 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1111 break
1112 }
1113 }
1114
1115 if len(updatedFlows) >= 0 {
1116 // There are still flows referencing the same flow_id.
1117 // So the flow should not be freed yet.
1118 // For ex: Case of HSIA where same flow is shared
1119 // between DS and US.
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001120 f.updateFlowInfoToKVStore(int32(ponIntf), int32(onuID), int32(uniID), flowID, &updatedFlows)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001121 if len(updatedFlows) == 0 {
1122 log.Debugw("Releasing flow Id to resource manager", log.Fields{"ponIntf": ponIntf, "onuId": onuID, "uniId": uniID, "flowId": flowID})
Devmalya Pauleb2e9552019-08-27 19:42:00 -04001123 f.resourceMgr.FreeFlowID(ponIntf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001124 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001125 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001126 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ponIntf, onuID, uniID)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001127 if len(flowIds) == 0 {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001128 log.Debugf("Flow count for subscriber %d is zero", onuID)
salmansiddiqui598eb8e2019-08-22 03:58:50 +00001129 kvstoreTpID := f.resourceMgr.GetTechProfileIDForOnu(ponIntf, onuID, uniID)
1130 if kvstoreTpID == 0 {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001131 log.Warnw("Could-not-find-techprofile-tableid-for-uni", log.Fields{"ponIntf": ponIntf, "onuId": onuID, "uniId": uniID})
1132 return
1133 }
1134 uni := getUniPortPath(ponIntf, onuID, uniID)
salmansiddiqui598eb8e2019-08-22 03:58:50 +00001135 tpPath := f.getTPpath(ponIntf, uni, kvstoreTpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001136 log.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
salmansiddiqui598eb8e2019-08-22 03:58:50 +00001137 techprofileInst, err := f.techprofile[ponIntf].GetTPInstanceFromKVStore(kvstoreTpID, tpPath)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001138 if err != nil { // This should not happen, something wrong in KV backend transaction
1139 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": 20, "path": tpPath})
1140 return
1141 }
1142 if techprofileInst == nil {
1143 log.Errorw("Tech-profile-instance-does-not-exist-in-KV Store", log.Fields{"tpPath": tpPath})
1144 return
1145 }
1146
1147 f.RemoveSchedulerQueues(tp_pb.Direction_UPSTREAM, ponIntf, onuID, uniID, portNum, techprofileInst)
1148 f.RemoveSchedulerQueues(tp_pb.Direction_DOWNSTREAM, ponIntf, onuID, uniID, portNum, techprofileInst)
1149 } else {
1150 log.Debugf("Flow ids for subscriber", log.Fields{"onu": onuID, "flows": flowIds})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001151 }
1152}
1153
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001154//RemoveFlow removes the flow from the device
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001155func (f *OpenOltFlowMgr) RemoveFlow(flow *ofp.OfpFlowStats) {
1156 log.Debugw("Removing Flow", log.Fields{"flow": flow})
1157 var deviceFlowsToRemove []ofp.OfpFlowStats
1158 var deletedFlowsIdx []int
1159 for _, curFlow := range f.storedDeviceFlows {
1160 if curFlow.Cookie == flow.Id {
1161 log.Debugw("Found found matching flow-cookie", log.Fields{"curFlow": curFlow})
1162 deviceFlowsToRemove = append(deviceFlowsToRemove, curFlow)
1163 }
1164 }
1165 log.Debugw("Flows to be deleted", log.Fields{"deviceFlowsToRemove": deviceFlowsToRemove})
1166 for index, curFlow := range deviceFlowsToRemove {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001167 id, direction := f.decodeStoredID(curFlow.GetId())
1168 removeFlowMessage := openoltpb2.Flow{FlowId: uint32(id), FlowType: direction}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001169 if ok := f.removeFlowFromDevice(&removeFlowMessage); ok {
1170 log.Debug("Flow removed from device successfully")
1171 deletedFlowsIdx = append(deletedFlowsIdx, index)
1172 f.clearFlowFromResourceManager(flow, uint32(id), direction) //TODO: Take care of the limitations
1173 }
1174
1175 }
1176 // Can be done in separate go routine as it takes time ?
1177 for _, flowToRemove := range deletedFlowsIdx {
1178 for index, storedFlow := range f.storedDeviceFlows {
1179 if deviceFlowsToRemove[flowToRemove].Cookie == storedFlow.Cookie {
1180 log.Debugw("Removing flow from local Store", log.Fields{"flow": storedFlow})
1181 f.storedDeviceFlows = append(f.storedDeviceFlows[:index], f.storedDeviceFlows[index+1:]...)
1182 break
1183 }
1184 }
1185 }
1186 log.Debugw("Flows removed from the data store",
1187 log.Fields{"number_of_flows_removed": len(deviceFlowsToRemove), "updated_stored_flows": f.storedDeviceFlows})
1188 return
1189}
1190
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001191// AddFlow add flow to device
Manikkaraj kb1d51442019-07-23 10:41:02 -04001192func (f *OpenOltFlowMgr) AddFlow(flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001193 classifierInfo := make(map[string]interface{})
1194 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001195 var UsMeterID uint32
1196 var DsMeterID uint32
1197
1198 log.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
salmansiddiqui598eb8e2019-08-22 03:58:50 +00001199 formulateClassifierInfoFromFlow(classifierInfo, flow)
1200
1201 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
1202 if err != nil {
1203 // Error logging is already done in the called function
1204 // So just return in case of error
1205 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301206 }
salmansiddiqui598eb8e2019-08-22 03:58:50 +00001207
manikkaraj k17652a72019-05-06 09:06:36 -04001208 /* Controller bound trap flows */
salmansiddiqui598eb8e2019-08-22 03:58:50 +00001209 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
1210 if err != nil {
1211 // error if any, already logged in the called function
1212 return
manikkaraj k17652a72019-05-06 09:06:36 -04001213 }
salmansiddiqui598eb8e2019-08-22 03:58:50 +00001214
1215 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[Output]})
1216 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001217 if ipProto, ok := classifierInfo[IPProto]; ok {
1218 if ipProto.(uint32) == IPProtoDhcp {
1219 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001220 if udpSrc.(uint32) == uint32(67) {
1221 log.Debug("trap-dhcp-from-nni-flow")
1222 f.addDHCPTrapFlowOnNNI(flow, classifierInfo, portNo)
1223 return
1224 }
1225 }
1226 }
1227 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001228 /* Metadata 8 bytes:
1229 Most Significant 2 Bytes = Inner VLAN
1230 Next 2 Bytes = Tech Profile ID(TPID)
1231 Least Significant 4 Bytes = Port ID
1232 Flow METADATA carries Tech-Profile (TP) ID and is mandatory in all
1233 subscriber related flows.
1234 */
1235 metadata := utils.GetMetadataFromWriteMetadataAction(flow)
1236 if metadata == 0 {
1237 log.Error("Metadata is not present in flow which is mandatory")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001238 return
1239 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001240 TpID := utils.GetTechProfileIDFromWriteMetaData(metadata)
salmansiddiqui598eb8e2019-08-22 03:58:50 +00001241 kvstoreTpID := f.resourceMgr.GetTechProfileIDForOnu(intfID, onuID, uniID)
1242 if kvstoreTpID == 0 {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001243 log.Debugf("tpid-not-present-in-kvstore, using tp id %d from flow metadata", TpID)
salmansiddiqui598eb8e2019-08-22 03:58:50 +00001244 } else if kvstoreTpID != uint32(TpID) {
1245 log.Error(" Tech-profile-updates-not-supported", log.Fields{"Tpid-in-flow": TpID, "kvstore-TpId": kvstoreTpID})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001246 return
1247 }
salmansiddiqui598eb8e2019-08-22 03:58:50 +00001248 log.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
1249 if IsUpstream(actionInfo[Output].(uint32)) {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001250 UsMeterID = utils.GetMeterIdFromFlow(flow)
1251 log.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
1252 } else {
1253 DsMeterID = utils.GetMeterIdFromFlow(flow)
1254 log.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
1255
1256 }
salmansiddiqui598eb8e2019-08-22 03:58:50 +00001257 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001258}
1259
1260//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04001261func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001262
1263 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301264 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001265 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301266 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301267 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301268 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04001269
Manikkaraj kb1d51442019-07-23 10:41:02 -04001270 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001271 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
manikkaraj k17652a72019-05-06 09:06:36 -04001272 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
1273 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1274 tpDownloadMsg,
1275 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
1276 f.deviceHandler.deviceType,
1277 onuDevice.Type,
1278 onuDevice.Id,
1279 onuDevice.ProxyAddress.DeviceId, "")
1280 if sendErr != nil {
1281 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1282 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1283 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1284 return sendErr
1285 }
1286 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05301287 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301288}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001289
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001290//UpdateOnuInfo function adds onu info to cache
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001291func (f *OpenOltFlowMgr) UpdateOnuInfo(intfID uint32, onuID uint32, serialNum string) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001292 onu := onuInfo{intfID: intfID, onuID: onuID, serialNumber: serialNum}
1293 onuIDkey := onuIDKey{intfID: intfID, onuID: onuID}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001294 f.onuIds[onuIDkey] = onu
1295 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
1296}
1297
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001298//addGemPortToOnuInfoMap function stores adds GEMport to ONU map
1299func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(intfID uint32, onuID uint32, gemPort uint32) {
1300 onuIDkey := onuIDKey{intfID: intfID, onuID: onuID}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001301 if val, ok := f.onuIds[onuIDkey]; ok {
1302 onuInfo := val
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001303 gemportKey := gemPortKey{intfID: intfID, gemPort: gemPort}
1304 f.onuGemPortIds[gemportKey] = onuInfo
1305 log.Debugw("Cached Gemport to Onuinfo map", log.Fields{"GemPort": gemPort, "intfId": onuInfo.intfID, "onuId": onuInfo.onuID})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001306 return
1307 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001308 log.Errorw("OnuInfo not found", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001309}
1310
1311// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001312
1313//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
1314func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
1315 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 -04001316 if serialNumber != "" {
1317 if onuInfo, ok := f.onuSerialNumbers[serialNumber]; ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001318 return onuInfo.onuID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001319 }
1320 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001321 gemportKey := gemPortKey{intfID: intfID, gemPort: gemPortID}
1322 if onuInfo, ok := f.onuGemPortIds[gemportKey]; ok {
1323 log.Debugw("Retrieved onu info from access", log.Fields{"intfId": intfID, "gemPortId": gemPortID, "onuId": onuInfo.onuID})
1324 return onuInfo.onuID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001325 }
1326 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001327 log.Errorw("onuid is not found", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPort": gemPortID})
1328 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 -04001329}
1330
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001331//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
1332func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001333 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001334 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001335 var err error
1336
1337 if packetIn.IntfType == "pon" {
1338 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001339 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001340 log.Errorw("Unable to get ONU ID from GEM/PON port", log.Fields{"pon port": packetIn.IntfId, "gemport": packetIn.GemportId})
1341 return logicalPortNum, err
1342 }
1343 if packetIn.PortNo != 0 {
1344 logicalPortNum = packetIn.PortNo
1345 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001346 uniID := uint32(0) // FIXME - multi-uni support
1347 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001348 }
1349 // 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 -07001350 pktInkey := packetInInfoKey{intfID: packetIn.IntfId, onuID: onuID, logicalPort: logicalPortNum}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001351 f.packetInGemPort[pktInkey] = packetIn.GemportId
1352 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001353 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001354 }
1355 log.Debugw("Retrieved logicalport from packet-in", log.Fields{"logicalPortNum": logicalPortNum, "IntfType": packetIn.IntfType})
1356 return logicalPortNum, nil
1357}
1358
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001359//GetPacketOutGemPortID returns gemPortId
1360func (f *OpenOltFlowMgr) GetPacketOutGemPortID(intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
1361 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001362 var err error
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001363 key := packetInInfoKey{intfID: intfID, onuID: onuID, logicalPort: portNum}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001364 if val, ok := f.packetInGemPort[key]; ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001365 gemPortID = val
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001366 } else {
1367 log.Errorw("Key-Error while fetching packet-out GEM port", log.Fields{"key": key})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001368 err = errors.New("key-error while fetching packet-out GEM port")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001369 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001370 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001371}
1372
Manikkaraj kb1d51442019-07-23 10:41:02 -04001373func installFlowOnAllGemports(
1374 f1 func(intfId uint32, onuId uint32, uniId uint32,
1375 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
1376 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32),
1377 f2 func(intfId uint32, onuId uint32, uniId uint32, portNo uint32,
1378 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32),
1379 args map[string]uint32,
1380 classifier map[string]interface{}, action map[string]interface{},
1381 logicalFlow *ofp.OfpFlowStats,
1382 gemPorts []uint32,
1383 FlowType string,
salmansiddiqui598eb8e2019-08-22 03:58:50 +00001384 vlanID ...uint32) {
1385 log.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
1386 for _, gemPortID := range gemPorts {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001387 if FlowType == HsiaFlow || FlowType == DhcpFlow {
salmansiddiqui598eb8e2019-08-22 03:58:50 +00001388 f1(args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001389 } else if FlowType == EapolFlow {
salmansiddiqui598eb8e2019-08-22 03:58:50 +00001390 f2(args["intfId"], args["onuId"], args["uniId"], args["portNo"], logicalFlow, args["allocId"], gemPortID, vlanID[0])
Manikkaraj kb1d51442019-07-23 10:41:02 -04001391 } else {
1392 log.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
1393 return
1394 }
1395 }
1396}
1397
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001398func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
1399 log.Debug("Adding trap-dhcp-of-nni-flow")
1400 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001401 classifier[PacketTagType] = DoubleTag
1402 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001403 /* We manage flowId resource pool on per PON port basis.
1404 Since this situation is tricky, as a hack, we pass the NNI port
1405 index (network_intf_id) as PON port Index for the flowId resource
1406 pool. Also, there is no ONU Id available for trapping DHCP packets
1407 on NNI port, use onu_id as -1 (invalid)
1408 ****************** CAVEAT *******************
1409 This logic works if the NNI Port Id falls within the same valid
1410 range of PON Port Ids. If this doesn't work for some OLT Vendor
1411 we need to have a re-look at this.
1412 *********************************************
1413 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001414 onuID := -1
1415 uniID := -1
1416 gemPortID := -1
1417 allocID := -1
1418 networkInterfaceID := f.deviceHandler.nniIntfID
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001419 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001420 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), flowStoreCookie); present {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001421 log.Debug("Flow-exists--not-re-adding")
1422 return
1423 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001424 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001425 if err != nil {
1426 log.Errorw("Flow id unavailable for DHCP traponNNI flow", log.Fields{"error": err})
1427 return
1428 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001429 var classifierProto *openoltpb2.Classifier
1430 var actionProto *openoltpb2.Action
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001431 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
1432 log.Error("Error in making classifier protobuf for dhcp trap on nni flow")
1433 return
1434 }
1435 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1436 if actionProto = makeOpenOltActionField(action); actionProto == nil {
1437 log.Error("Error in making action protobuf for dhcp trap on nni flow")
1438 return
1439 }
1440 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001441 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1442 OnuId: int32(onuID), // OnuId not required
1443 UniId: int32(uniID), // UniId not used
1444 FlowId: flowID,
salmansiddiqui598eb8e2019-08-22 03:58:50 +00001445 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001446 AllocId: int32(allocID), // AllocId not used
1447 NetworkIntfId: int32(networkInterfaceID),
1448 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001449 Classifier: classifierProto,
1450 Action: actionProto,
1451 Priority: int32(logicalFlow.Priority),
1452 Cookie: logicalFlow.Cookie,
1453 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001454 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001455 log.Debug("DHCP trap on NNI flow added to device successfully")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001456 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID)
1457 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1458 int32(onuID),
1459 int32(uniID),
1460 flowID, flowsToKVStore); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001461 log.Errorw("Error uploading DHCP DL flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1462 }
1463 }
1464 return
1465}
salmansiddiqui598eb8e2019-08-22 03:58:50 +00001466
1467func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
1468 if MeterID == 0 { // This should never happen
1469 log.Error("Invalid meter id")
1470 return "", errors.New("invalid meter id")
1471 }
1472 if Dir == tp_pb.Direction_UPSTREAM {
1473 return "upstream", nil
1474 } else if Dir == tp_pb.Direction_DOWNSTREAM {
1475 return "downstream", nil
1476 }
1477 return "", nil
1478}
1479
1480func (f *OpenOltFlowMgr) checkAndAddFlow(args map[string]uint32, classifierInfo map[string]interface{},
1481 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, gemPort, intfID, onuID, uniID, portNo uint32,
1482 TpInst *tp.TechProfile, allocID []uint32, gemPorts []uint32, TpID uint32, uni string) {
1483 if ipProto, ok := classifierInfo[IPProto]; ok {
1484 if ipProto.(uint32) == IPProtoDhcp {
1485 log.Info("Adding DHCP flow")
1486 if pcp, ok := classifierInfo[VlanPcp]; ok {
1487 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1488 tp_pb.Direction_UPSTREAM,
1489 pcp.(uint32))
1490 //Adding DHCP upstream flow
1491 f.addDHCPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
1492 } else {
1493 //Adding DHCP upstream flow to all gemports
1494 installFlowOnAllGemports(f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, DhcpFlow)
1495 }
1496
1497 } else if ipProto == IgmpProto {
1498 log.Info("igmp flow add ignored, not implemented yet")
1499 return
1500 } else {
1501 log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
1502 return
1503 }
1504 } else if ethType, ok := classifierInfo[EthType]; ok {
1505 if ethType.(uint32) == EapEthType {
1506 log.Info("Adding EAPOL flow")
1507 var vlanID uint32
1508 if val, ok := classifierInfo[VlanVid]; ok {
1509 vlanID = (val.(uint32)) & VlanvIDMask
1510 } else {
1511 vlanID = DefaultMgmtVlan
1512 }
1513 if pcp, ok := classifierInfo[VlanPcp]; ok {
1514 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1515 tp_pb.Direction_UPSTREAM,
1516 pcp.(uint32))
1517
1518 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID[0], gemPort, vlanID)
1519 } else {
1520 installFlowOnAllGemports(nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, EapolFlow, vlanID)
1521 }
1522 }
1523 if ethType == LldpEthType {
1524 log.Info("Adding LLDP flow")
1525 addLLDPFlow(flow, portNo)
1526 return
1527 }
1528 } else if _, ok := actionInfo[PushVlan]; ok {
1529 log.Info("Adding upstream data rule")
1530 if pcp, ok := classifierInfo[VlanPcp]; ok {
1531 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1532 tp_pb.Direction_UPSTREAM,
1533 pcp.(uint32))
1534 //Adding HSIA upstream flow
1535 f.addUpstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
1536 } else {
1537 //Adding HSIA upstream flow to all gemports
1538 installFlowOnAllGemports(f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1539 }
1540 } else if _, ok := actionInfo[PopVlan]; ok {
1541 log.Info("Adding Downstream data rule")
1542 if pcp, ok := classifierInfo[VlanPcp]; ok {
1543 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana017f1ba892019-09-03 15:41:40 -05001544 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui598eb8e2019-08-22 03:58:50 +00001545 pcp.(uint32))
1546 //Adding HSIA downstream flow
1547 f.addDownstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
1548 } else {
1549 //Adding HSIA downstream flow to all gemports
1550 installFlowOnAllGemports(f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1551 }
1552 } else {
1553 log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
1554 return
1555 }
1556 // Send Techprofile download event to child device in go routine as it takes time
1557 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, TpID)
1558}
1559
1560func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
1561 for _, field := range utils.GetOfbFields(flow) {
1562 if field.Type == utils.ETH_TYPE {
1563 classifierInfo[EthType] = field.GetEthType()
1564 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
1565 } else if field.Type == utils.IP_PROTO {
1566 classifierInfo[IPProto] = field.GetIpProto()
1567 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
1568 } else if field.Type == utils.IN_PORT {
1569 classifierInfo[InPort] = field.GetPort()
1570 log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
1571 } else if field.Type == utils.VLAN_VID {
1572 classifierInfo[VlanVid] = field.GetVlanVid()
1573 log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
1574 } else if field.Type == utils.VLAN_PCP {
1575 classifierInfo[VlanPcp] = field.GetVlanPcp()
1576 log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
1577 } else if field.Type == utils.UDP_DST {
1578 classifierInfo[UDPDst] = field.GetUdpDst()
1579 log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
1580 } else if field.Type == utils.UDP_SRC {
1581 classifierInfo[UDPSrc] = field.GetUdpSrc()
1582 log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
1583 } else if field.Type == utils.IPV4_DST {
1584 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
1585 log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
1586 } else if field.Type == utils.IPV4_SRC {
1587 classifierInfo[Ipv4Src] = field.GetIpv4Src()
1588 log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
1589 } else if field.Type == utils.METADATA {
1590 classifierInfo[Metadata] = field.GetTableMetadata()
1591 log.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
1592 } else if field.Type == utils.TUNNEL_ID {
1593 classifierInfo[TunnelID] = field.GetTunnelId()
1594 log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
1595 } else {
1596 log.Errorw("Un supported field type", log.Fields{"type": field.Type})
1597 return
1598 }
1599 }
1600}
1601
1602func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
1603 for _, action := range utils.GetActions(flow) {
1604 if action.Type == utils.OUTPUT {
1605 if out := action.GetOutput(); out != nil {
1606 actionInfo[Output] = out.GetPort()
1607 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
1608 } else {
1609 log.Error("Invalid output port in action")
1610 return errors.New("invalid output port in action")
1611 }
1612 } else if action.Type == utils.POP_VLAN {
1613 actionInfo[PopVlan] = true
1614 log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
1615 } else if action.Type == utils.PUSH_VLAN {
1616 if out := action.GetPush(); out != nil {
1617 if tpid := out.GetEthertype(); tpid != 0x8100 {
1618 log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
1619 } else {
1620 actionInfo[PushVlan] = true
1621 actionInfo[TPID] = tpid
1622 log.Debugw("action-type-push-vlan",
1623 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
1624 }
1625 }
1626 } else if action.Type == utils.SET_FIELD {
1627 if out := action.GetSetField(); out != nil {
1628 if field := out.GetField(); field != nil {
1629 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
1630 log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
1631 return errors.New("invalid openflow class")
1632 }
1633 /*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
1634 if ofbField := field.GetOfbField(); ofbField != nil {
1635 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
1636 if vlan := ofbField.GetVlanVid(); vlan != 0 {
1637 actionInfo[VlanVid] = vlan & 0xfff
1638 log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
1639 } else {
1640 log.Error("No Invalid vlan id in set vlan-vid action")
1641 }
1642 } else {
1643 log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
1644 }
1645 }
1646 }
1647 }
1648 } else {
1649 log.Errorw("Un supported action type", log.Fields{"type": action.Type})
1650 return errors.New("un supported action type")
1651 }
1652 }
1653 return nil
1654}
1655
1656func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
1657 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
1658 log.Debug("Controller bound trap flows, getting inport from tunnelid")
1659 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
1660 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
1661 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
1662 classifierInfo[InPort] = uniPort
1663 log.Debugw("upstream pon-to-controller-flow,inport-in-tunnelid", log.Fields{"newInPort": classifierInfo[InPort].(uint32), "outPort": actionInfo[Output].(uint32)})
1664 } else {
1665 log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1666 return errors.New("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1667 }
1668 }
1669 } else {
1670 log.Debug("Non-Controller flows, getting uniport from tunnelid")
1671 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
1672 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
1673 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
1674 actionInfo[Output] = uniPort
1675 log.Debugw("downstream-nni-to-pon-port-flow, outport-in-tunnelid", log.Fields{"newOutPort": actionInfo[Output].(uint32), "outPort": actionInfo[Output].(uint32)})
1676 } else {
1677 log.Debug("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid", log.Fields{"InPort": classifierInfo[InPort].(uint32), "outPort": actionInfo[Output].(uint32)})
1678 return errors.New("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid")
1679 }
1680 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
1681 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
1682 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
1683 classifierInfo[InPort] = uniPort
1684 log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[Output].(uint32),
1685 "outport": actionInfo[Output].(uint32)})
1686 } else {
1687 log.Debug("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid", log.Fields{"InPort": classifierInfo[InPort].(uint32),
1688 "outPort": actionInfo[Output].(uint32)})
1689 return errors.New("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid")
1690 }
1691 }
1692 }
1693 return nil
1694}