blob: 4b3be6a728d5c4204a093b353694ffe1d2b8e5af [file] [log] [blame]
manikkaraj kbf256be2019-03-25 00:13:48 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070017//Package adaptercore provides the utility for olt devices, flows and statistics
manikkaraj kbf256be2019-03-25 00:13:48 +053018package adaptercore
19
20import (
21 "context"
22 "crypto/md5"
23 "encoding/json"
24 "errors"
25 "fmt"
Manikkaraj kb1d51442019-07-23 10:41:02 -040026 "math/big"
27
manikkaraj kbf256be2019-03-25 00:13:48 +053028 "github.com/opencord/voltha-go/common/log"
29 tp "github.com/opencord/voltha-go/common/techprofile"
Matt Jeannereta93dbed2019-05-17 12:40:05 -040030 "github.com/opencord/voltha-go/rw_core/utils"
Manikkaraj k884c1242019-04-11 16:26:42 +053031 rsrcMgr "github.com/opencord/voltha-openolt-adapter/adaptercore/resourcemanager"
manikkaraj k17652a72019-05-06 09:06:36 -040032 ic "github.com/opencord/voltha-protos/go/inter_container"
manikkaraj kbf256be2019-03-25 00:13:48 +053033 ofp "github.com/opencord/voltha-protos/go/openflow_13"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070034 openoltpb2 "github.com/opencord/voltha-protos/go/openolt"
Manikkaraj kb1d51442019-07-23 10:41:02 -040035 tp_pb "github.com/opencord/voltha-protos/go/tech_profile"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070036 "github.com/opencord/voltha-protos/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040037
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -040038 //deepcopy "github.com/getlantern/deepcopy"
Daniele Rossi22db98e2019-07-11 11:50:00 +000039 "google.golang.org/grpc/codes"
40 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053041)
42
43const (
44 // Flow categories
manikkaraj kbf256be2019-03-25 00:13:48 +053045
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070046 //HsiaFlow flow category
47 HsiaFlow = "HSIA_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053048
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070049 //EapolFlow flow category
50 EapolFlow = "EAPOL_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053051
Manikkaraj kb1d51442019-07-23 10:41:02 -040052 //DhcpFlow flow category
53 DhcpFlow = "DHCP_FLOW"
54
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070055 //IPProtoDhcp flow category
56 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053057
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070058 //IPProtoIgmp flow category
59 IPProtoIgmp = 2
60
61 //EapEthType eapethtype value
62 EapEthType = 0x888e
63 //LldpEthType lldp ethtype value
64 LldpEthType = 0x88cc
65
66 //IgmpProto proto value
67 IgmpProto = 2
manikkaraj kbf256be2019-03-25 00:13:48 +053068
69 //FIXME - see also BRDCM_DEFAULT_VLAN in broadcom_onu.py
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070070
David K. Bainbridge82efc492019-09-04 09:57:11 -070071 // ReservedVlan Transparent Vlan
72 ReservedVlan = 4095
Harsh Awasthiea45af72019-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
David K. Bainbridge82efc492019-09-04 09:57:11 -070079 //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"
David K. Bainbridge82efc492019-09-04 09:57:11 -070085 //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"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700115 //Metadata constant
116 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700117 //TunnelID constant
118 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700119 //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) {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700193 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
David K. Bainbridge82efc492019-09-04 09:57:11 -0700196 } 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
salmansiddiqui7ac62132019-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,
salmansiddiqui7ac62132019-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})
salmansiddiqui7ac62132019-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
salmansiddiqui7ac62132019-08-22 03:58:50 +0000253 args["allocId"] = allocID[0]
Manikkaraj kb1d51442019-07-23 10:41:02 -0400254
salmansiddiqui7ac62132019-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
salmansiddiqui7ac62132019-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
salmansiddiqui7ac62132019-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
salmansiddiqui7ac62132019-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 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000273
Manikkaraj kb1d51442019-07-23 10:41:02 -0400274 var SchedCfg *tp_pb.SchedulerConfig
salmansiddiqui7ac62132019-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 {
salmansiddiqui7ac62132019-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 {
salmansiddiqui7ac62132019-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 }
salmansiddiqui7ac62132019-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 }
salmansiddiqui7ac62132019-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 {
salmansiddiqui7ac62132019-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 {
salmansiddiqui7ac62132019-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 {
salmansiddiqui7ac62132019-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 {
salmansiddiqui7ac62132019-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 {
salmansiddiqui7ac62132019-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
salmansiddiqui7ac62132019-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{
salmansiddiqui7ac62132019-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.
salmansiddiqui7ac62132019-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(),
salmansiddiqui7ac62132019-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
salmansiddiqui7ac62132019-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 */
salmansiddiqui7ac62132019-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
salmansiddiqui7ac62132019-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
salmansiddiqui7ac62132019-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 {
salmansiddiqui7ac62132019-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 {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000366 SchedCfg = f.techprofile[IntfID].GetDsScheduler(TpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400367 Direction = "downstream"
368 }
369
salmansiddiqui7ac62132019-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 {
salmansiddiqui7ac62132019-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 {
salmansiddiqui7ac62132019-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
salmansiddiqui7ac62132019-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(),
salmansiddiqui7ac62132019-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 {
salmansiddiqui7ac62132019-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 }
salmansiddiqui7ac62132019-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{
salmansiddiqui7ac62132019-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 {
salmansiddiqui7ac62132019-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
salmansiddiqui7ac62132019-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 */
salmansiddiqui7ac62132019-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 {
salmansiddiqui7ac62132019-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
salmansiddiqui7ac62132019-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
salmansiddiqui7ac62132019-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
salmansiddiqui7ac62132019-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})
salmansiddiqui7ac62132019-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 }
salmansiddiqui7ac62132019-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 {
salmansiddiqui7ac62132019-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 {
salmansiddiqui7ac62132019-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
salmansiddiqui7ac62132019-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
salmansiddiqui7ac62132019-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)
salmansiddiqui7ac62132019-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 {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000499 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530500 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-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++
salmansiddiqui7ac62132019-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()})
salmansiddiqui7ac62132019-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,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700525 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
David K. Bainbridge82efc492019-09-04 09:57:11 -0700539 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,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700552 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})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000568 var vlanPit uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400569 if _, ok := classifier[VlanPcp]; ok {
salmansiddiqui7ac62132019-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)
salmansiddiqui7ac62132019-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),
salmansiddiqui7ac62132019-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})
salmansiddiqui7ac62132019-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,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700660 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,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700728 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)
salmansiddiqui7ac62132019-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",
salmansiddiqui7ac62132019-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),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000798 FlowId: downlinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700799 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 := ""
salmansiddiqui7ac62132019-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
David K. Bainbridge82efc492019-09-04 09:57:11 -0700828
829 classifier.EthType, _ = classifierInfo[EthType].(uint32)
830 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
831 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
832 vid := vlanID & VlanvIDMask
833 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -0400834 classifier.OVid = vid
835 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530836 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700837 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
838 vid := uint32(metadata)
839 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -0400840 classifier.IVid = vid
841 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530842 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700843 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400844 if vlanPcp == 0 {
845 classifier.OPbits = VlanPCPMask
846 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700847 classifier.OPbits = vlanPcp & VlanPCPMask
Manikkaraj kb1d51442019-07-23 10:41:02 -0400848 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530849 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700850 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
851 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
852 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
853 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
854 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
855 classifier.PktTagType = pktTagType
856
857 switch pktTagType {
858 case SingleTag:
859 case DoubleTag:
860 case Untagged:
861 default:
manikkaraj kbf256be2019-03-25 00:13:48 +0530862 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
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700892func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530893 if len(classifier) == 0 { // should never happen
894 log.Error("Invalid classfier object")
895 return 0
896 }
897 var jsonData []byte
898 var flowString string
899 var err error
900 // TODO: Do we need to marshall ??
901 if jsonData, err = json.Marshal(classifier); err != nil {
902 log.Error("Failed to encode classifier")
903 return 0
904 }
905 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700906 if gemPortID != 0 {
907 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +0530908 }
909 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700910 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +0530911 hash := big.NewInt(0)
912 hash.SetBytes(h.Sum(nil))
913 return hash.Uint64()
914}
915
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700916func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openoltpb2.Flow, flowStoreCookie uint64, flowCategory string, deviceFlowID uint32) *[]rsrcMgr.FlowInfo {
917 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
918 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400919 /* For flows which trap out of the NNI, the AccessIntfId is invalid
920 (set to -1). In such cases, we need to refer to the NetworkIntfId .
921 */
922 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700923 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400924 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700925 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400926 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700927 // Get existing flows matching flowid for given subscriber from KV store
928 existingFlows := f.resourceMgr.GetFlowIDInfo(intfID, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -0400929 if existingFlows != nil {
930 log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700931 //for _, f := range *existingFlows {
932 // flows = append(flows, f)
933 //}
934 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -0400935 }
936 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 +0530937 return &flows
938}
939
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400940//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
941// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
942// var intfId uint32
943// /* For flows which trap out of the NNI, the AccessIntfId is invalid
944// (set to -1). In such cases, we need to refer to the NetworkIntfId .
945// */
946// if flow.AccessIntfId != -1 {
947// intfId = uint32(flow.AccessIntfId)
948// } else {
949// intfId = uint32(flow.NetworkIntfId)
950// }
951// // Get existing flows matching flowid for given subscriber from KV store
952// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
953// if existingFlows != nil {
954// log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
955// for _, f := range *existingFlows {
956// flows = append(flows, f)
957// }
958// }
959// log.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
960// return &flows
961//}
962
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700963func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
manikkaraj k17652a72019-05-06 09:06:36 -0400964 log.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700965 if err := f.resourceMgr.UpdateFlowIDInfo(intfID, onuID, uniID, flowID, flows); err != nil {
manikkaraj k17652a72019-05-06 09:06:36 -0400966 log.Debug("Error while Storing flow into KV store")
967 return err
968 }
969 log.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +0530970 return nil
971}
972
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700973func (f *OpenOltFlowMgr) addFlowToDevice(logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) bool {
Daniele Rossi22db98e2019-07-11 11:50:00 +0000974
975 var intfID uint32
976 /* For flows which trap out of the NNI, the AccessIntfId is invalid
977 (set to -1). In such cases, we need to refer to the NetworkIntfId .
978 */
979 if deviceFlow.AccessIntfId != -1 {
980 intfID = uint32(deviceFlow.AccessIntfId)
981 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400982 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +0000983 intfID = uint32(deviceFlow.NetworkIntfId)
984 }
985
manikkaraj kbf256be2019-03-25 00:13:48 +0530986 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
987 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +0000988
989 st, _ := status.FromError(err)
990 if st.Code() == codes.AlreadyExists {
991 log.Debug("Flow already exixts", log.Fields{"err": err, "deviceFlow": deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +0530992 return false
993 }
Daniele Rossi22db98e2019-07-11 11:50:00 +0000994
995 if err != nil {
996 log.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": deviceFlow})
997 f.resourceMgr.FreeFlowID(intfID, uint32(deviceFlow.OnuId), uint32(deviceFlow.UniId), deviceFlow.FlowId)
998 return false
999 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001000 log.Debugw("Flow added to device successfully ", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001001 f.registerFlow(logicalFlow, deviceFlow)
1002 return true
1003}
1004
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001005func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) bool {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001006 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1007 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1008 if err != nil {
1009 log.Errorw("Failed to Remove flow from device", log.Fields{"err": err, "deviceFlow": deviceFlow})
1010 return false
1011 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001012 log.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301013 return true
1014}
1015
1016/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1017 //update core flows_proxy : flows_proxy.update('/', flows)
1018}
1019
1020func generateStoredId(flowId uint32, direction string)uint32{
1021
David K. Bainbridge82efc492019-09-04 09:57:11 -07001022 if direction == Upstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301023 log.Debug("Upstream flow shifting flowid")
1024 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001025 }else if direction == Downstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301026 log.Debug("Downstream flow not shifting flowid")
1027 return flowId
1028 }else{
1029 log.Errorw("Unrecognized direction",log.Fields{"direction": direction})
1030 return flowId
1031 }
1032}
1033
1034*/
1035
1036func addLLDPFlow(flow *ofp.OfpFlowStats, portNo uint32) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001037 log.Info("unimplemented flow : %v, portNo : %v ", flow, portNo)
manikkaraj kbf256be2019-03-25 00:13:48 +05301038}
1039
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001040func getUniPortPath(intfID uint32, onuID uint32, uniID uint32) string {
1041 return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1042}
1043
1044//getOnuChildDevice to fetch onu
1045func (f *OpenOltFlowMgr) getOnuChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
1046 log.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
1047 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
1048 onuDevice := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301049 if onuDevice == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001050 log.Errorw("onu not found", log.Fields{"intfId": parentPortNo, "onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301051 return nil, errors.New("onu not found")
manikkaraj kbf256be2019-03-25 00:13:48 +05301052 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301053 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1054 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301055}
1056
1057func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001058 log.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301059 return nil
1060}
1061
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001062func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
1063 log.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301064}
1065
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001066func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001067 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001068 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001069 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001070 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001071}
1072
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001073func (f *OpenOltFlowMgr) clearFlowFromResourceManager(flow *ofp.OfpFlowStats, flowID uint32, flowDirection string) {
1074 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowID": flowID, "flowDirection": flowDirection, "flow": *flow})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001075 portNum, ponIntf, onuID, uniID, err := FlowExtractInfo(flow, flowDirection)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001076 if err != nil {
1077 log.Error(err)
1078 return
1079 }
1080 log.Debugw("Extracted access info from flow to be deleted",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001081 log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001082
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001083 flowsInfo := f.resourceMgr.GetFlowIDInfo(ponIntf, onuID, uniID, flowID)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001084 if flowsInfo == nil {
1085 log.Debugw("No FlowInfo found found in KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001086 log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001087 return
1088 }
1089 var updatedFlows []rsrcMgr.FlowInfo
1090
1091 for _, flow := range *flowsInfo {
1092 updatedFlows = append(updatedFlows, flow)
1093 }
1094
1095 for i, storedFlow := range updatedFlows {
1096 if flowDirection == storedFlow.Flow.FlowType {
1097 //Remove the Flow from FlowInfo
1098 log.Debugw("Removing flow to be deleted", log.Fields{"flow": storedFlow})
1099 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1100 break
1101 }
1102 }
1103
1104 if len(updatedFlows) >= 0 {
1105 // There are still flows referencing the same flow_id.
1106 // So the flow should not be freed yet.
1107 // For ex: Case of HSIA where same flow is shared
1108 // between DS and US.
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001109 f.updateFlowInfoToKVStore(int32(ponIntf), int32(onuID), int32(uniID), flowID, &updatedFlows)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001110 if len(updatedFlows) == 0 {
1111 log.Debugw("Releasing flow Id to resource manager", log.Fields{"ponIntf": ponIntf, "onuId": onuID, "uniId": uniID, "flowId": flowID})
1112 f.resourceMgr.FreeFlowID(ponIntf, onuID, uniID, flowID)
1113 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001114 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001115 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ponIntf, onuID, uniID)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001116 if len(flowIds) == 0 {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001117 log.Debugf("Flow count for subscriber %d is zero", onuID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001118 kvstoreTpID := f.resourceMgr.GetTechProfileIDForOnu(ponIntf, onuID, uniID)
1119 if kvstoreTpID == 0 {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001120 log.Warnw("Could-not-find-techprofile-tableid-for-uni", log.Fields{"ponIntf": ponIntf, "onuId": onuID, "uniId": uniID})
1121 return
1122 }
1123 uni := getUniPortPath(ponIntf, onuID, uniID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001124 tpPath := f.getTPpath(ponIntf, uni, kvstoreTpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001125 log.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001126 techprofileInst, err := f.techprofile[ponIntf].GetTPInstanceFromKVStore(kvstoreTpID, tpPath)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001127 if err != nil { // This should not happen, something wrong in KV backend transaction
1128 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": 20, "path": tpPath})
1129 return
1130 }
1131 if techprofileInst == nil {
1132 log.Errorw("Tech-profile-instance-does-not-exist-in-KV Store", log.Fields{"tpPath": tpPath})
1133 return
1134 }
1135
1136 f.RemoveSchedulerQueues(tp_pb.Direction_UPSTREAM, ponIntf, onuID, uniID, portNum, techprofileInst)
1137 f.RemoveSchedulerQueues(tp_pb.Direction_DOWNSTREAM, ponIntf, onuID, uniID, portNum, techprofileInst)
1138 } else {
1139 log.Debugf("Flow ids for subscriber", log.Fields{"onu": onuID, "flows": flowIds})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001140 }
1141}
1142
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001143//RemoveFlow removes the flow from the device
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001144func (f *OpenOltFlowMgr) RemoveFlow(flow *ofp.OfpFlowStats) {
1145 log.Debugw("Removing Flow", log.Fields{"flow": flow})
1146 var deviceFlowsToRemove []ofp.OfpFlowStats
1147 var deletedFlowsIdx []int
1148 for _, curFlow := range f.storedDeviceFlows {
1149 if curFlow.Cookie == flow.Id {
1150 log.Debugw("Found found matching flow-cookie", log.Fields{"curFlow": curFlow})
1151 deviceFlowsToRemove = append(deviceFlowsToRemove, curFlow)
1152 }
1153 }
1154 log.Debugw("Flows to be deleted", log.Fields{"deviceFlowsToRemove": deviceFlowsToRemove})
1155 for index, curFlow := range deviceFlowsToRemove {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001156 id, direction := f.decodeStoredID(curFlow.GetId())
1157 removeFlowMessage := openoltpb2.Flow{FlowId: uint32(id), FlowType: direction}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001158 if ok := f.removeFlowFromDevice(&removeFlowMessage); ok {
1159 log.Debug("Flow removed from device successfully")
1160 deletedFlowsIdx = append(deletedFlowsIdx, index)
1161 f.clearFlowFromResourceManager(flow, uint32(id), direction) //TODO: Take care of the limitations
1162 }
1163
1164 }
1165 // Can be done in separate go routine as it takes time ?
1166 for _, flowToRemove := range deletedFlowsIdx {
1167 for index, storedFlow := range f.storedDeviceFlows {
1168 if deviceFlowsToRemove[flowToRemove].Cookie == storedFlow.Cookie {
1169 log.Debugw("Removing flow from local Store", log.Fields{"flow": storedFlow})
1170 f.storedDeviceFlows = append(f.storedDeviceFlows[:index], f.storedDeviceFlows[index+1:]...)
1171 break
1172 }
1173 }
1174 }
1175 log.Debugw("Flows removed from the data store",
1176 log.Fields{"number_of_flows_removed": len(deviceFlowsToRemove), "updated_stored_flows": f.storedDeviceFlows})
1177 return
1178}
1179
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001180// AddFlow add flow to device
Manikkaraj kb1d51442019-07-23 10:41:02 -04001181func (f *OpenOltFlowMgr) AddFlow(flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001182 classifierInfo := make(map[string]interface{})
1183 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001184 var UsMeterID uint32
1185 var DsMeterID uint32
1186
1187 log.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001188 formulateClassifierInfoFromFlow(classifierInfo, flow)
1189
1190 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
1191 if err != nil {
1192 // Error logging is already done in the called function
1193 // So just return in case of error
1194 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301195 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001196
manikkaraj k17652a72019-05-06 09:06:36 -04001197 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00001198 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
1199 if err != nil {
1200 // error if any, already logged in the called function
1201 return
manikkaraj k17652a72019-05-06 09:06:36 -04001202 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001203
David K. Bainbridge82efc492019-09-04 09:57:11 -07001204 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[Output]})
1205 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001206 if ipProto, ok := classifierInfo[IPProto]; ok {
1207 if ipProto.(uint32) == IPProtoDhcp {
1208 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001209 if udpSrc.(uint32) == uint32(67) {
1210 log.Debug("trap-dhcp-from-nni-flow")
1211 f.addDHCPTrapFlowOnNNI(flow, classifierInfo, portNo)
1212 return
1213 }
1214 }
1215 }
1216 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001217 /* Metadata 8 bytes:
1218 Most Significant 2 Bytes = Inner VLAN
1219 Next 2 Bytes = Tech Profile ID(TPID)
1220 Least Significant 4 Bytes = Port ID
David K. Bainbridge82efc492019-09-04 09:57:11 -07001221 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
Manikkaraj kb1d51442019-07-23 10:41:02 -04001222 subscriber related flows.
1223 */
1224 metadata := utils.GetMetadataFromWriteMetadataAction(flow)
1225 if metadata == 0 {
1226 log.Error("Metadata is not present in flow which is mandatory")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001227 return
1228 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001229 TpID := utils.GetTechProfileIDFromWriteMetaData(metadata)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001230 kvstoreTpID := f.resourceMgr.GetTechProfileIDForOnu(intfID, onuID, uniID)
1231 if kvstoreTpID == 0 {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001232 log.Debugf("tpid-not-present-in-kvstore, using tp id %d from flow metadata", TpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001233 } else if kvstoreTpID != uint32(TpID) {
1234 log.Error(" Tech-profile-updates-not-supported", log.Fields{"Tpid-in-flow": TpID, "kvstore-TpId": kvstoreTpID})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001235 return
1236 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001237 log.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001238 if IsUpstream(actionInfo[Output].(uint32)) {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001239 UsMeterID = utils.GetMeterIdFromFlow(flow)
1240 log.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
1241 } else {
1242 DsMeterID = utils.GetMeterIdFromFlow(flow)
1243 log.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
1244
1245 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001246 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001247}
1248
1249//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04001250func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001251
1252 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301253 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001254 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301255 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301256 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301257 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04001258
Manikkaraj kb1d51442019-07-23 10:41:02 -04001259 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001260 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
manikkaraj k17652a72019-05-06 09:06:36 -04001261 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
1262 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1263 tpDownloadMsg,
1264 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
1265 f.deviceHandler.deviceType,
1266 onuDevice.Type,
1267 onuDevice.Id,
1268 onuDevice.ProxyAddress.DeviceId, "")
1269 if sendErr != nil {
1270 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1271 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1272 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1273 return sendErr
1274 }
1275 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05301276 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301277}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001278
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001279//UpdateOnuInfo function adds onu info to cache
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001280func (f *OpenOltFlowMgr) UpdateOnuInfo(intfID uint32, onuID uint32, serialNum string) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001281 onu := onuInfo{intfID: intfID, onuID: onuID, serialNumber: serialNum}
1282 onuIDkey := onuIDKey{intfID: intfID, onuID: onuID}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001283 f.onuIds[onuIDkey] = onu
1284 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
1285}
1286
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001287//addGemPortToOnuInfoMap function stores adds GEMport to ONU map
1288func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(intfID uint32, onuID uint32, gemPort uint32) {
1289 onuIDkey := onuIDKey{intfID: intfID, onuID: onuID}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001290 if val, ok := f.onuIds[onuIDkey]; ok {
1291 onuInfo := val
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001292 gemportKey := gemPortKey{intfID: intfID, gemPort: gemPort}
1293 f.onuGemPortIds[gemportKey] = onuInfo
1294 log.Debugw("Cached Gemport to Onuinfo map", log.Fields{"GemPort": gemPort, "intfId": onuInfo.intfID, "onuId": onuInfo.onuID})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001295 return
1296 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001297 log.Errorw("OnuInfo not found", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001298}
1299
1300// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001301
1302//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
1303func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
1304 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 -04001305 if serialNumber != "" {
1306 if onuInfo, ok := f.onuSerialNumbers[serialNumber]; ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001307 return onuInfo.onuID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001308 }
1309 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001310 gemportKey := gemPortKey{intfID: intfID, gemPort: gemPortID}
1311 if onuInfo, ok := f.onuGemPortIds[gemportKey]; ok {
1312 log.Debugw("Retrieved onu info from access", log.Fields{"intfId": intfID, "gemPortId": gemPortID, "onuId": onuInfo.onuID})
1313 return onuInfo.onuID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001314 }
1315 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001316 log.Errorw("onuid is not found", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPort": gemPortID})
1317 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 -04001318}
1319
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001320//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
1321func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001322 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001323 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001324 var err error
1325
1326 if packetIn.IntfType == "pon" {
1327 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001328 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001329 log.Errorw("Unable to get ONU ID from GEM/PON port", log.Fields{"pon port": packetIn.IntfId, "gemport": packetIn.GemportId})
1330 return logicalPortNum, err
1331 }
1332 if packetIn.PortNo != 0 {
1333 logicalPortNum = packetIn.PortNo
1334 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001335 uniID := uint32(0) // FIXME - multi-uni support
1336 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001337 }
1338 // 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 -07001339 pktInkey := packetInInfoKey{intfID: packetIn.IntfId, onuID: onuID, logicalPort: logicalPortNum}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001340 f.packetInGemPort[pktInkey] = packetIn.GemportId
1341 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001342 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001343 }
1344 log.Debugw("Retrieved logicalport from packet-in", log.Fields{"logicalPortNum": logicalPortNum, "IntfType": packetIn.IntfType})
1345 return logicalPortNum, nil
1346}
1347
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001348//GetPacketOutGemPortID returns gemPortId
1349func (f *OpenOltFlowMgr) GetPacketOutGemPortID(intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
1350 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001351 var err error
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001352 key := packetInInfoKey{intfID: intfID, onuID: onuID, logicalPort: portNum}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001353 if val, ok := f.packetInGemPort[key]; ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001354 gemPortID = val
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001355 } else {
1356 log.Errorw("Key-Error while fetching packet-out GEM port", log.Fields{"key": key})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001357 err = errors.New("key-error while fetching packet-out GEM port")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001358 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001359 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001360}
1361
Manikkaraj kb1d51442019-07-23 10:41:02 -04001362func installFlowOnAllGemports(
1363 f1 func(intfId uint32, onuId uint32, uniId uint32,
1364 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
1365 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32),
1366 f2 func(intfId uint32, onuId uint32, uniId uint32, portNo uint32,
1367 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32),
1368 args map[string]uint32,
1369 classifier map[string]interface{}, action map[string]interface{},
1370 logicalFlow *ofp.OfpFlowStats,
1371 gemPorts []uint32,
1372 FlowType string,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001373 vlanID ...uint32) {
1374 log.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
1375 for _, gemPortID := range gemPorts {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001376 if FlowType == HsiaFlow || FlowType == DhcpFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001377 f1(args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001378 } else if FlowType == EapolFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001379 f2(args["intfId"], args["onuId"], args["uniId"], args["portNo"], logicalFlow, args["allocId"], gemPortID, vlanID[0])
Manikkaraj kb1d51442019-07-23 10:41:02 -04001380 } else {
1381 log.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
1382 return
1383 }
1384 }
1385}
1386
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001387func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
1388 log.Debug("Adding trap-dhcp-of-nni-flow")
1389 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001390 classifier[PacketTagType] = DoubleTag
1391 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001392 /* We manage flowId resource pool on per PON port basis.
1393 Since this situation is tricky, as a hack, we pass the NNI port
1394 index (network_intf_id) as PON port Index for the flowId resource
1395 pool. Also, there is no ONU Id available for trapping DHCP packets
1396 on NNI port, use onu_id as -1 (invalid)
1397 ****************** CAVEAT *******************
1398 This logic works if the NNI Port Id falls within the same valid
1399 range of PON Port Ids. If this doesn't work for some OLT Vendor
1400 we need to have a re-look at this.
1401 *********************************************
1402 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001403 onuID := -1
1404 uniID := -1
1405 gemPortID := -1
1406 allocID := -1
1407 networkInterfaceID := f.deviceHandler.nniIntfID
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001408 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001409 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), flowStoreCookie); present {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001410 log.Debug("Flow-exists--not-re-adding")
1411 return
1412 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001413 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001414 if err != nil {
1415 log.Errorw("Flow id unavailable for DHCP traponNNI flow", log.Fields{"error": err})
1416 return
1417 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001418 var classifierProto *openoltpb2.Classifier
1419 var actionProto *openoltpb2.Action
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001420 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
1421 log.Error("Error in making classifier protobuf for dhcp trap on nni flow")
1422 return
1423 }
1424 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1425 if actionProto = makeOpenOltActionField(action); actionProto == nil {
1426 log.Error("Error in making action protobuf for dhcp trap on nni flow")
1427 return
1428 }
1429 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001430 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1431 OnuId: int32(onuID), // OnuId not required
1432 UniId: int32(uniID), // UniId not used
1433 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001434 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001435 AllocId: int32(allocID), // AllocId not used
1436 NetworkIntfId: int32(networkInterfaceID),
1437 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001438 Classifier: classifierProto,
1439 Action: actionProto,
1440 Priority: int32(logicalFlow.Priority),
1441 Cookie: logicalFlow.Cookie,
1442 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001443 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001444 log.Debug("DHCP trap on NNI flow added to device successfully")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001445 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID)
1446 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1447 int32(onuID),
1448 int32(uniID),
1449 flowID, flowsToKVStore); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001450 log.Errorw("Error uploading DHCP DL flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1451 }
1452 }
1453 return
1454}
salmansiddiqui7ac62132019-08-22 03:58:50 +00001455
1456func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
1457 if MeterID == 0 { // This should never happen
1458 log.Error("Invalid meter id")
1459 return "", errors.New("invalid meter id")
1460 }
1461 if Dir == tp_pb.Direction_UPSTREAM {
1462 return "upstream", nil
1463 } else if Dir == tp_pb.Direction_DOWNSTREAM {
1464 return "downstream", nil
1465 }
1466 return "", nil
1467}
1468
1469func (f *OpenOltFlowMgr) checkAndAddFlow(args map[string]uint32, classifierInfo map[string]interface{},
1470 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, gemPort, intfID, onuID, uniID, portNo uint32,
1471 TpInst *tp.TechProfile, allocID []uint32, gemPorts []uint32, TpID uint32, uni string) {
1472 if ipProto, ok := classifierInfo[IPProto]; ok {
1473 if ipProto.(uint32) == IPProtoDhcp {
1474 log.Info("Adding DHCP flow")
1475 if pcp, ok := classifierInfo[VlanPcp]; ok {
1476 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1477 tp_pb.Direction_UPSTREAM,
1478 pcp.(uint32))
1479 //Adding DHCP upstream flow
1480 f.addDHCPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
1481 } else {
1482 //Adding DHCP upstream flow to all gemports
1483 installFlowOnAllGemports(f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, DhcpFlow)
1484 }
1485
1486 } else if ipProto == IgmpProto {
1487 log.Info("igmp flow add ignored, not implemented yet")
1488 return
1489 } else {
1490 log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
1491 return
1492 }
1493 } else if ethType, ok := classifierInfo[EthType]; ok {
1494 if ethType.(uint32) == EapEthType {
1495 log.Info("Adding EAPOL flow")
1496 var vlanID uint32
1497 if val, ok := classifierInfo[VlanVid]; ok {
1498 vlanID = (val.(uint32)) & VlanvIDMask
1499 } else {
1500 vlanID = DefaultMgmtVlan
1501 }
1502 if pcp, ok := classifierInfo[VlanPcp]; ok {
1503 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1504 tp_pb.Direction_UPSTREAM,
1505 pcp.(uint32))
1506
1507 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID[0], gemPort, vlanID)
1508 } else {
1509 installFlowOnAllGemports(nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, EapolFlow, vlanID)
1510 }
1511 }
1512 if ethType == LldpEthType {
1513 log.Info("Adding LLDP flow")
1514 addLLDPFlow(flow, portNo)
1515 return
1516 }
1517 } else if _, ok := actionInfo[PushVlan]; ok {
1518 log.Info("Adding upstream data rule")
1519 if pcp, ok := classifierInfo[VlanPcp]; ok {
1520 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1521 tp_pb.Direction_UPSTREAM,
1522 pcp.(uint32))
1523 //Adding HSIA upstream flow
1524 f.addUpstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
1525 } else {
1526 //Adding HSIA upstream flow to all gemports
1527 installFlowOnAllGemports(f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1528 }
1529 } else if _, ok := actionInfo[PopVlan]; ok {
1530 log.Info("Adding Downstream data rule")
1531 if pcp, ok := classifierInfo[VlanPcp]; ok {
1532 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1533 tp_pb.Direction_UPSTREAM,
1534 pcp.(uint32))
1535 //Adding HSIA downstream flow
1536 f.addDownstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
1537 } else {
1538 //Adding HSIA downstream flow to all gemports
1539 installFlowOnAllGemports(f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1540 }
1541 } else {
1542 log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
1543 return
1544 }
1545 // Send Techprofile download event to child device in go routine as it takes time
1546 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, TpID)
1547}
1548
1549func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
1550 for _, field := range utils.GetOfbFields(flow) {
1551 if field.Type == utils.ETH_TYPE {
1552 classifierInfo[EthType] = field.GetEthType()
1553 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
1554 } else if field.Type == utils.IP_PROTO {
1555 classifierInfo[IPProto] = field.GetIpProto()
1556 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
1557 } else if field.Type == utils.IN_PORT {
1558 classifierInfo[InPort] = field.GetPort()
1559 log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
1560 } else if field.Type == utils.VLAN_VID {
1561 classifierInfo[VlanVid] = field.GetVlanVid()
1562 log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
1563 } else if field.Type == utils.VLAN_PCP {
1564 classifierInfo[VlanPcp] = field.GetVlanPcp()
1565 log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
1566 } else if field.Type == utils.UDP_DST {
1567 classifierInfo[UDPDst] = field.GetUdpDst()
1568 log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
1569 } else if field.Type == utils.UDP_SRC {
1570 classifierInfo[UDPSrc] = field.GetUdpSrc()
1571 log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
1572 } else if field.Type == utils.IPV4_DST {
1573 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
1574 log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
1575 } else if field.Type == utils.IPV4_SRC {
1576 classifierInfo[Ipv4Src] = field.GetIpv4Src()
1577 log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
1578 } else if field.Type == utils.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001579 classifierInfo[Metadata] = field.GetTableMetadata()
1580 log.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001581 } else if field.Type == utils.TUNNEL_ID {
1582 classifierInfo[TunnelID] = field.GetTunnelId()
1583 log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
1584 } else {
1585 log.Errorw("Un supported field type", log.Fields{"type": field.Type})
1586 return
1587 }
1588 }
1589}
1590
1591func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
1592 for _, action := range utils.GetActions(flow) {
1593 if action.Type == utils.OUTPUT {
1594 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001595 actionInfo[Output] = out.GetPort()
1596 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001597 } else {
1598 log.Error("Invalid output port in action")
1599 return errors.New("invalid output port in action")
1600 }
1601 } else if action.Type == utils.POP_VLAN {
1602 actionInfo[PopVlan] = true
1603 log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
1604 } else if action.Type == utils.PUSH_VLAN {
1605 if out := action.GetPush(); out != nil {
1606 if tpid := out.GetEthertype(); tpid != 0x8100 {
1607 log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
1608 } else {
1609 actionInfo[PushVlan] = true
1610 actionInfo[TPID] = tpid
1611 log.Debugw("action-type-push-vlan",
1612 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
1613 }
1614 }
1615 } else if action.Type == utils.SET_FIELD {
1616 if out := action.GetSetField(); out != nil {
1617 if field := out.GetField(); field != nil {
1618 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
1619 log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
1620 return errors.New("invalid openflow class")
1621 }
1622 /*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
1623 if ofbField := field.GetOfbField(); ofbField != nil {
1624 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
1625 if vlan := ofbField.GetVlanVid(); vlan != 0 {
1626 actionInfo[VlanVid] = vlan & 0xfff
1627 log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
1628 } else {
1629 log.Error("No Invalid vlan id in set vlan-vid action")
1630 }
1631 } else {
1632 log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
1633 }
1634 }
1635 }
1636 }
1637 } else {
1638 log.Errorw("Un supported action type", log.Fields{"type": action.Type})
1639 return errors.New("un supported action type")
1640 }
1641 }
1642 return nil
1643}
1644
1645func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001646 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001647 log.Debug("Controller bound trap flows, getting inport from tunnelid")
1648 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
1649 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
1650 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
1651 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07001652 log.Debugw("upstream pon-to-controller-flow,inport-in-tunnelid", log.Fields{"newInPort": classifierInfo[InPort].(uint32), "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001653 } else {
1654 log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1655 return errors.New("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1656 }
1657 }
1658 } else {
1659 log.Debug("Non-Controller flows, getting uniport from tunnelid")
1660 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07001661 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001662 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001663 actionInfo[Output] = uniPort
1664 log.Debugw("downstream-nni-to-pon-port-flow, outport-in-tunnelid", log.Fields{"newOutPort": actionInfo[Output].(uint32), "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001665 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001666 log.Debug("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid", log.Fields{"InPort": classifierInfo[InPort].(uint32), "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001667 return errors.New("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid")
1668 }
1669 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
1670 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
1671 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
1672 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07001673 log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[Output].(uint32),
1674 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001675 } else {
1676 log.Debug("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid", log.Fields{"InPort": classifierInfo[InPort].(uint32),
David K. Bainbridge82efc492019-09-04 09:57:11 -07001677 "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001678 return errors.New("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid")
1679 }
1680 }
1681 }
1682 return nil
1683}