blob: e99d36e09fbad4593936fc4fcf052f21001a8160 [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
Humera Kouser94d7a842019-08-25 19:04:32 -040071 //ReservedVlan Transparent Vlan
David K. Bainbridge82efc492019-09-04 09:57:11 -070072 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
Devmalya Paul495b94a2019-08-27 19:42:00 -0400892// DeleteTechProfileInstance removes the tech profile instance from persistent storage
893func (f *OpenOltFlowMgr) DeleteTechProfileInstance(intfID uint32, onuID uint32, uniID uint32, sn string) error {
894 tpID := f.resourceMgr.GetTechProfileIDForOnu(intfID, onuID, uniID)
895 uniPortName := fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
896 if err := f.techprofile[intfID].DeleteTechProfileInstance(tpID, uniPortName); err != nil {
897 log.Debugw("Failed-to-delete-tp-instance-from-kv-store", log.Fields{"tp-id": tpID, "uni-port-name": uniPortName})
898 return err
899 }
900 return nil
901}
902
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700903func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530904 if len(classifier) == 0 { // should never happen
905 log.Error("Invalid classfier object")
906 return 0
907 }
908 var jsonData []byte
909 var flowString string
910 var err error
911 // TODO: Do we need to marshall ??
912 if jsonData, err = json.Marshal(classifier); err != nil {
913 log.Error("Failed to encode classifier")
914 return 0
915 }
916 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700917 if gemPortID != 0 {
918 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +0530919 }
920 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700921 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +0530922 hash := big.NewInt(0)
923 hash.SetBytes(h.Sum(nil))
924 return hash.Uint64()
925}
926
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700927func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openoltpb2.Flow, flowStoreCookie uint64, flowCategory string, deviceFlowID uint32) *[]rsrcMgr.FlowInfo {
928 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
929 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400930 /* For flows which trap out of the NNI, the AccessIntfId is invalid
931 (set to -1). In such cases, we need to refer to the NetworkIntfId .
932 */
933 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700934 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400935 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700936 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400937 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700938 // Get existing flows matching flowid for given subscriber from KV store
939 existingFlows := f.resourceMgr.GetFlowIDInfo(intfID, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -0400940 if existingFlows != nil {
941 log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700942 //for _, f := range *existingFlows {
943 // flows = append(flows, f)
944 //}
945 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -0400946 }
947 log.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
manikkaraj kbf256be2019-03-25 00:13:48 +0530948 return &flows
949}
950
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400951//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
952// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
953// var intfId uint32
954// /* For flows which trap out of the NNI, the AccessIntfId is invalid
955// (set to -1). In such cases, we need to refer to the NetworkIntfId .
956// */
957// if flow.AccessIntfId != -1 {
958// intfId = uint32(flow.AccessIntfId)
959// } else {
960// intfId = uint32(flow.NetworkIntfId)
961// }
962// // Get existing flows matching flowid for given subscriber from KV store
963// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
964// if existingFlows != nil {
965// log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
966// for _, f := range *existingFlows {
967// flows = append(flows, f)
968// }
969// }
970// log.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
971// return &flows
972//}
973
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700974func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
manikkaraj k17652a72019-05-06 09:06:36 -0400975 log.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700976 if err := f.resourceMgr.UpdateFlowIDInfo(intfID, onuID, uniID, flowID, flows); err != nil {
manikkaraj k17652a72019-05-06 09:06:36 -0400977 log.Debug("Error while Storing flow into KV store")
978 return err
979 }
980 log.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +0530981 return nil
982}
983
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700984func (f *OpenOltFlowMgr) addFlowToDevice(logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) bool {
Daniele Rossi22db98e2019-07-11 11:50:00 +0000985
986 var intfID uint32
987 /* For flows which trap out of the NNI, the AccessIntfId is invalid
988 (set to -1). In such cases, we need to refer to the NetworkIntfId .
989 */
990 if deviceFlow.AccessIntfId != -1 {
991 intfID = uint32(deviceFlow.AccessIntfId)
992 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400993 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +0000994 intfID = uint32(deviceFlow.NetworkIntfId)
995 }
996
manikkaraj kbf256be2019-03-25 00:13:48 +0530997 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
998 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +0000999
1000 st, _ := status.FromError(err)
1001 if st.Code() == codes.AlreadyExists {
1002 log.Debug("Flow already exixts", log.Fields{"err": err, "deviceFlow": deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301003 return false
1004 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001005
1006 if err != nil {
1007 log.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": deviceFlow})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001008 f.resourceMgr.FreeFlowID(intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001009 return false
1010 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001011 log.Debugw("Flow added to device successfully ", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001012 f.registerFlow(logicalFlow, deviceFlow)
1013 return true
1014}
1015
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001016func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) bool {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001017 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1018 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1019 if err != nil {
1020 log.Errorw("Failed to Remove flow from device", log.Fields{"err": err, "deviceFlow": deviceFlow})
1021 return false
1022 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001023 log.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301024 return true
1025}
1026
1027/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1028 //update core flows_proxy : flows_proxy.update('/', flows)
1029}
1030
1031func generateStoredId(flowId uint32, direction string)uint32{
1032
David K. Bainbridge82efc492019-09-04 09:57:11 -07001033 if direction == Upstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301034 log.Debug("Upstream flow shifting flowid")
1035 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001036 }else if direction == Downstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301037 log.Debug("Downstream flow not shifting flowid")
1038 return flowId
1039 }else{
1040 log.Errorw("Unrecognized direction",log.Fields{"direction": direction})
1041 return flowId
1042 }
1043}
1044
1045*/
1046
Humera Kouser94d7a842019-08-25 19:04:32 -04001047func (f *OpenOltFlowMgr) addLLDPFlow(flow *ofp.OfpFlowStats, portNo uint32) {
1048
1049 classifierInfo := make(map[string]interface{})
1050 actionInfo := make(map[string]interface{})
1051
1052 classifierInfo[EthType] = uint32(LldpEthType)
1053 classifierInfo[PacketTagType] = Untagged
1054 actionInfo[TrapToHost] = true
1055
1056 // LLDP flow is installed to trap LLDP packets on the NNI port.
1057 // We manage flow_id resource pool on per PON port basis.
1058 // Since this situation is tricky, as a hack, we pass the NNI port
1059 // index (network_intf_id) as PON port Index for the flow_id resource
1060 // pool. Also, there is no ONU Id available for trapping LLDP packets
1061 // on NNI port, use onu_id as -1 (invalid)
1062 // ****************** CAVEAT *******************
1063 // This logic works if the NNI Port Id falls within the same valid
1064 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1065 // we need to have a re-look at this.
1066 // *********************************************
1067
1068 var onuID = -1
1069 var uniID = -1
1070 var gemPortID = -1
1071
1072 var networkInterfaceID = IntfIDFromNniPortNum(portNo)
1073 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
1074 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), flowStoreCookie); present {
1075 log.Debug("Flow-exists--not-re-adding")
1076 return
1077 }
1078 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
1079
1080 if err != nil {
1081 log.Errorw("Flow id unavailable for LLDP traponNNI flow", log.Fields{"error": err})
1082 return
1083 }
1084 var classifierProto *openoltpb2.Classifier
1085 var actionProto *openoltpb2.Action
1086 if classifierProto = makeOpenOltClassifierField(classifierInfo); classifierProto == nil {
1087 log.Error("Error in making classifier protobuf for LLDP trap on nni flow")
1088 return
1089 }
1090 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1091 if actionProto = makeOpenOltActionField(actionInfo); actionProto == nil {
1092 log.Error("Error in making action protobuf for LLDP trap on nni flow")
1093 return
1094 }
1095 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
1096
1097 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1098 OnuId: int32(onuID), // OnuId not required
1099 UniId: int32(uniID), // UniId not used
1100 FlowId: flowID,
1101 FlowType: Downstream,
1102 NetworkIntfId: int32(networkInterfaceID),
1103 GemportId: int32(gemPortID),
1104 Classifier: classifierProto,
1105 Action: actionProto,
1106 Priority: int32(flow.Priority),
1107 Cookie: flow.Cookie,
1108 PortNo: portNo}
1109 if ok := f.addFlowToDevice(flow, &downstreamflow); ok {
1110 log.Debug("LLDP trap on NNI flow added to device successfully")
1111 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID)
1112 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1113 int32(onuID),
1114 int32(uniID),
1115 flowID, flowsToKVStore); err != nil {
1116 log.Errorw("Error uploading LLDP flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1117 }
1118 }
1119 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301120}
1121
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001122func getUniPortPath(intfID uint32, onuID uint32, uniID uint32) string {
1123 return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1124}
1125
1126//getOnuChildDevice to fetch onu
1127func (f *OpenOltFlowMgr) getOnuChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
1128 log.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
1129 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
1130 onuDevice := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301131 if onuDevice == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001132 log.Errorw("onu not found", log.Fields{"intfId": parentPortNo, "onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301133 return nil, errors.New("onu not found")
manikkaraj kbf256be2019-03-25 00:13:48 +05301134 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301135 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1136 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301137}
1138
1139func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001140 log.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301141 return nil
1142}
1143
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001144func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
1145 log.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301146}
1147
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001148func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001149 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001150 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001151 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001152 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001153}
1154
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001155func (f *OpenOltFlowMgr) clearFlowFromResourceManager(flow *ofp.OfpFlowStats, flowID uint32, flowDirection string) {
1156 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowID": flowID, "flowDirection": flowDirection, "flow": *flow})
Humera Kouser94d7a842019-08-25 19:04:32 -04001157 portNum, ponIntf, onuID, uniID, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001158 if err != nil {
1159 log.Error(err)
1160 return
1161 }
1162 log.Debugw("Extracted access info from flow to be deleted",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001163 log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001164
Humera Kouser94d7a842019-08-25 19:04:32 -04001165 if ethType == LldpEthType {
1166 var networkInterfaceID uint32
1167 var onuID = -1
1168 var uniID = -1
1169
1170 networkInterfaceID = IntfIDFromNniPortNum(inPort)
1171 f.resourceMgr.FreeFlowID(networkInterfaceID, int32(onuID), int32(uniID), flowID)
1172 return
1173 }
1174
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001175 flowsInfo := f.resourceMgr.GetFlowIDInfo(ponIntf, onuID, uniID, flowID)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001176 if flowsInfo == nil {
1177 log.Debugw("No FlowInfo found found in KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001178 log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001179 return
1180 }
1181 var updatedFlows []rsrcMgr.FlowInfo
1182
1183 for _, flow := range *flowsInfo {
1184 updatedFlows = append(updatedFlows, flow)
1185 }
1186
1187 for i, storedFlow := range updatedFlows {
1188 if flowDirection == storedFlow.Flow.FlowType {
1189 //Remove the Flow from FlowInfo
1190 log.Debugw("Removing flow to be deleted", log.Fields{"flow": storedFlow})
1191 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1192 break
1193 }
1194 }
1195
1196 if len(updatedFlows) >= 0 {
1197 // There are still flows referencing the same flow_id.
1198 // So the flow should not be freed yet.
1199 // For ex: Case of HSIA where same flow is shared
1200 // between DS and US.
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001201 f.updateFlowInfoToKVStore(int32(ponIntf), int32(onuID), int32(uniID), flowID, &updatedFlows)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001202 if len(updatedFlows) == 0 {
1203 log.Debugw("Releasing flow Id to resource manager", log.Fields{"ponIntf": ponIntf, "onuId": onuID, "uniId": uniID, "flowId": flowID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001204 f.resourceMgr.FreeFlowID(ponIntf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001205 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001206 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001207 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ponIntf, onuID, uniID)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001208 if len(flowIds) == 0 {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001209 log.Debugf("Flow count for subscriber %d is zero", onuID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001210 kvstoreTpID := f.resourceMgr.GetTechProfileIDForOnu(ponIntf, onuID, uniID)
1211 if kvstoreTpID == 0 {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001212 log.Warnw("Could-not-find-techprofile-tableid-for-uni", log.Fields{"ponIntf": ponIntf, "onuId": onuID, "uniId": uniID})
1213 return
1214 }
1215 uni := getUniPortPath(ponIntf, onuID, uniID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001216 tpPath := f.getTPpath(ponIntf, uni, kvstoreTpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001217 log.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001218 techprofileInst, err := f.techprofile[ponIntf].GetTPInstanceFromKVStore(kvstoreTpID, tpPath)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001219 if err != nil { // This should not happen, something wrong in KV backend transaction
1220 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": 20, "path": tpPath})
1221 return
1222 }
1223 if techprofileInst == nil {
1224 log.Errorw("Tech-profile-instance-does-not-exist-in-KV Store", log.Fields{"tpPath": tpPath})
1225 return
1226 }
1227
1228 f.RemoveSchedulerQueues(tp_pb.Direction_UPSTREAM, ponIntf, onuID, uniID, portNum, techprofileInst)
1229 f.RemoveSchedulerQueues(tp_pb.Direction_DOWNSTREAM, ponIntf, onuID, uniID, portNum, techprofileInst)
1230 } else {
1231 log.Debugf("Flow ids for subscriber", log.Fields{"onu": onuID, "flows": flowIds})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001232 }
1233}
1234
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001235//RemoveFlow removes the flow from the device
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001236func (f *OpenOltFlowMgr) RemoveFlow(flow *ofp.OfpFlowStats) {
1237 log.Debugw("Removing Flow", log.Fields{"flow": flow})
1238 var deviceFlowsToRemove []ofp.OfpFlowStats
1239 var deletedFlowsIdx []int
1240 for _, curFlow := range f.storedDeviceFlows {
1241 if curFlow.Cookie == flow.Id {
1242 log.Debugw("Found found matching flow-cookie", log.Fields{"curFlow": curFlow})
1243 deviceFlowsToRemove = append(deviceFlowsToRemove, curFlow)
1244 }
1245 }
1246 log.Debugw("Flows to be deleted", log.Fields{"deviceFlowsToRemove": deviceFlowsToRemove})
1247 for index, curFlow := range deviceFlowsToRemove {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001248 id, direction := f.decodeStoredID(curFlow.GetId())
1249 removeFlowMessage := openoltpb2.Flow{FlowId: uint32(id), FlowType: direction}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001250 if ok := f.removeFlowFromDevice(&removeFlowMessage); ok {
1251 log.Debug("Flow removed from device successfully")
1252 deletedFlowsIdx = append(deletedFlowsIdx, index)
1253 f.clearFlowFromResourceManager(flow, uint32(id), direction) //TODO: Take care of the limitations
1254 }
1255
1256 }
1257 // Can be done in separate go routine as it takes time ?
1258 for _, flowToRemove := range deletedFlowsIdx {
1259 for index, storedFlow := range f.storedDeviceFlows {
1260 if deviceFlowsToRemove[flowToRemove].Cookie == storedFlow.Cookie {
1261 log.Debugw("Removing flow from local Store", log.Fields{"flow": storedFlow})
1262 f.storedDeviceFlows = append(f.storedDeviceFlows[:index], f.storedDeviceFlows[index+1:]...)
1263 break
1264 }
1265 }
1266 }
1267 log.Debugw("Flows removed from the data store",
1268 log.Fields{"number_of_flows_removed": len(deviceFlowsToRemove), "updated_stored_flows": f.storedDeviceFlows})
1269 return
1270}
1271
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001272// AddFlow add flow to device
Manikkaraj kb1d51442019-07-23 10:41:02 -04001273func (f *OpenOltFlowMgr) AddFlow(flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001274 classifierInfo := make(map[string]interface{})
1275 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001276 var UsMeterID uint32
1277 var DsMeterID uint32
1278
1279 log.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001280 formulateClassifierInfoFromFlow(classifierInfo, flow)
1281
1282 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
1283 if err != nil {
1284 // Error logging is already done in the called function
1285 // So just return in case of error
1286 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301287 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001288
manikkaraj k17652a72019-05-06 09:06:36 -04001289 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00001290 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
1291 if err != nil {
1292 // error if any, already logged in the called function
1293 return
manikkaraj k17652a72019-05-06 09:06:36 -04001294 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001295
David K. Bainbridge82efc492019-09-04 09:57:11 -07001296 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[Output]})
1297 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
Humera Kouser94d7a842019-08-25 19:04:32 -04001298 if ethType, ok := classifierInfo[EthType]; ok {
1299 if ethType.(uint32) == LldpEthType {
1300 log.Info("Adding LLDP flow")
1301 f.addLLDPFlow(flow, portNo)
1302 return
1303 }
1304 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001305 if ipProto, ok := classifierInfo[IPProto]; ok {
1306 if ipProto.(uint32) == IPProtoDhcp {
1307 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001308 if udpSrc.(uint32) == uint32(67) {
1309 log.Debug("trap-dhcp-from-nni-flow")
1310 f.addDHCPTrapFlowOnNNI(flow, classifierInfo, portNo)
1311 return
1312 }
1313 }
1314 }
1315 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001316 /* Metadata 8 bytes:
1317 Most Significant 2 Bytes = Inner VLAN
1318 Next 2 Bytes = Tech Profile ID(TPID)
1319 Least Significant 4 Bytes = Port ID
David K. Bainbridge82efc492019-09-04 09:57:11 -07001320 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
Manikkaraj kb1d51442019-07-23 10:41:02 -04001321 subscriber related flows.
1322 */
1323 metadata := utils.GetMetadataFromWriteMetadataAction(flow)
1324 if metadata == 0 {
1325 log.Error("Metadata is not present in flow which is mandatory")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001326 return
1327 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001328 TpID := utils.GetTechProfileIDFromWriteMetaData(metadata)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001329 kvstoreTpID := f.resourceMgr.GetTechProfileIDForOnu(intfID, onuID, uniID)
1330 if kvstoreTpID == 0 {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001331 log.Debugf("tpid-not-present-in-kvstore, using tp id %d from flow metadata", TpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001332 } else if kvstoreTpID != uint32(TpID) {
1333 log.Error(" Tech-profile-updates-not-supported", log.Fields{"Tpid-in-flow": TpID, "kvstore-TpId": kvstoreTpID})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001334 return
1335 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001336 log.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001337 if IsUpstream(actionInfo[Output].(uint32)) {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001338 UsMeterID = utils.GetMeterIdFromFlow(flow)
1339 log.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
1340 } else {
1341 DsMeterID = utils.GetMeterIdFromFlow(flow)
1342 log.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
1343
1344 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001345 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001346}
1347
1348//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04001349func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001350
1351 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301352 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001353 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301354 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301355 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301356 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04001357
Manikkaraj kb1d51442019-07-23 10:41:02 -04001358 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001359 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
manikkaraj k17652a72019-05-06 09:06:36 -04001360 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
1361 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1362 tpDownloadMsg,
1363 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
1364 f.deviceHandler.deviceType,
1365 onuDevice.Type,
1366 onuDevice.Id,
1367 onuDevice.ProxyAddress.DeviceId, "")
1368 if sendErr != nil {
1369 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1370 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1371 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1372 return sendErr
1373 }
1374 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05301375 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301376}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001377
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001378//UpdateOnuInfo function adds onu info to cache
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001379func (f *OpenOltFlowMgr) UpdateOnuInfo(intfID uint32, onuID uint32, serialNum string) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001380 onu := onuInfo{intfID: intfID, onuID: onuID, serialNumber: serialNum}
1381 onuIDkey := onuIDKey{intfID: intfID, onuID: onuID}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001382 f.onuIds[onuIDkey] = onu
1383 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
1384}
1385
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001386//addGemPortToOnuInfoMap function stores adds GEMport to ONU map
1387func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(intfID uint32, onuID uint32, gemPort uint32) {
1388 onuIDkey := onuIDKey{intfID: intfID, onuID: onuID}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001389 if val, ok := f.onuIds[onuIDkey]; ok {
1390 onuInfo := val
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001391 gemportKey := gemPortKey{intfID: intfID, gemPort: gemPort}
1392 f.onuGemPortIds[gemportKey] = onuInfo
1393 log.Debugw("Cached Gemport to Onuinfo map", log.Fields{"GemPort": gemPort, "intfId": onuInfo.intfID, "onuId": onuInfo.onuID})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001394 return
1395 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001396 log.Errorw("OnuInfo not found", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001397}
1398
1399// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001400
1401//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
1402func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
1403 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 -04001404 if serialNumber != "" {
1405 if onuInfo, ok := f.onuSerialNumbers[serialNumber]; ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001406 return onuInfo.onuID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001407 }
1408 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001409 gemportKey := gemPortKey{intfID: intfID, gemPort: gemPortID}
1410 if onuInfo, ok := f.onuGemPortIds[gemportKey]; ok {
1411 log.Debugw("Retrieved onu info from access", log.Fields{"intfId": intfID, "gemPortId": gemPortID, "onuId": onuInfo.onuID})
1412 return onuInfo.onuID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001413 }
1414 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001415 log.Errorw("onuid is not found", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPort": gemPortID})
1416 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 -04001417}
1418
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001419//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
1420func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001421 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001422 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001423 var err error
1424
1425 if packetIn.IntfType == "pon" {
1426 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001427 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001428 log.Errorw("Unable to get ONU ID from GEM/PON port", log.Fields{"pon port": packetIn.IntfId, "gemport": packetIn.GemportId})
1429 return logicalPortNum, err
1430 }
1431 if packetIn.PortNo != 0 {
1432 logicalPortNum = packetIn.PortNo
1433 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001434 uniID := uint32(0) // FIXME - multi-uni support
1435 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001436 }
1437 // 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 -07001438 pktInkey := packetInInfoKey{intfID: packetIn.IntfId, onuID: onuID, logicalPort: logicalPortNum}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001439 f.packetInGemPort[pktInkey] = packetIn.GemportId
1440 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001441 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001442 }
1443 log.Debugw("Retrieved logicalport from packet-in", log.Fields{"logicalPortNum": logicalPortNum, "IntfType": packetIn.IntfType})
1444 return logicalPortNum, nil
1445}
1446
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001447//GetPacketOutGemPortID returns gemPortId
1448func (f *OpenOltFlowMgr) GetPacketOutGemPortID(intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
1449 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001450 var err error
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001451 key := packetInInfoKey{intfID: intfID, onuID: onuID, logicalPort: portNum}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001452 if val, ok := f.packetInGemPort[key]; ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001453 gemPortID = val
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001454 } else {
1455 log.Errorw("Key-Error while fetching packet-out GEM port", log.Fields{"key": key})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001456 err = errors.New("key-error while fetching packet-out GEM port")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001457 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001458 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001459}
1460
Manikkaraj kb1d51442019-07-23 10:41:02 -04001461func installFlowOnAllGemports(
1462 f1 func(intfId uint32, onuId uint32, uniId uint32,
1463 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
1464 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32),
1465 f2 func(intfId uint32, onuId uint32, uniId uint32, portNo uint32,
1466 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32),
1467 args map[string]uint32,
1468 classifier map[string]interface{}, action map[string]interface{},
1469 logicalFlow *ofp.OfpFlowStats,
1470 gemPorts []uint32,
1471 FlowType string,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001472 vlanID ...uint32) {
1473 log.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
1474 for _, gemPortID := range gemPorts {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001475 if FlowType == HsiaFlow || FlowType == DhcpFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001476 f1(args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001477 } else if FlowType == EapolFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001478 f2(args["intfId"], args["onuId"], args["uniId"], args["portNo"], logicalFlow, args["allocId"], gemPortID, vlanID[0])
Manikkaraj kb1d51442019-07-23 10:41:02 -04001479 } else {
1480 log.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
1481 return
1482 }
1483 }
1484}
1485
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001486func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
1487 log.Debug("Adding trap-dhcp-of-nni-flow")
1488 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001489 classifier[PacketTagType] = DoubleTag
1490 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001491 /* We manage flowId resource pool on per PON port basis.
1492 Since this situation is tricky, as a hack, we pass the NNI port
1493 index (network_intf_id) as PON port Index for the flowId resource
1494 pool. Also, there is no ONU Id available for trapping DHCP packets
1495 on NNI port, use onu_id as -1 (invalid)
1496 ****************** CAVEAT *******************
1497 This logic works if the NNI Port Id falls within the same valid
1498 range of PON Port Ids. If this doesn't work for some OLT Vendor
1499 we need to have a re-look at this.
1500 *********************************************
1501 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001502 onuID := -1
1503 uniID := -1
1504 gemPortID := -1
1505 allocID := -1
1506 networkInterfaceID := f.deviceHandler.nniIntfID
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001507 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001508 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), flowStoreCookie); present {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001509 log.Debug("Flow-exists--not-re-adding")
1510 return
1511 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001512 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001513 if err != nil {
1514 log.Errorw("Flow id unavailable for DHCP traponNNI flow", log.Fields{"error": err})
1515 return
1516 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001517 var classifierProto *openoltpb2.Classifier
1518 var actionProto *openoltpb2.Action
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001519 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
1520 log.Error("Error in making classifier protobuf for dhcp trap on nni flow")
1521 return
1522 }
1523 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1524 if actionProto = makeOpenOltActionField(action); actionProto == nil {
1525 log.Error("Error in making action protobuf for dhcp trap on nni flow")
1526 return
1527 }
1528 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001529 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1530 OnuId: int32(onuID), // OnuId not required
1531 UniId: int32(uniID), // UniId not used
1532 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001533 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001534 AllocId: int32(allocID), // AllocId not used
1535 NetworkIntfId: int32(networkInterfaceID),
1536 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001537 Classifier: classifierProto,
1538 Action: actionProto,
1539 Priority: int32(logicalFlow.Priority),
1540 Cookie: logicalFlow.Cookie,
1541 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001542 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001543 log.Debug("DHCP trap on NNI flow added to device successfully")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001544 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID)
1545 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1546 int32(onuID),
1547 int32(uniID),
1548 flowID, flowsToKVStore); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001549 log.Errorw("Error uploading DHCP DL flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1550 }
1551 }
1552 return
1553}
salmansiddiqui7ac62132019-08-22 03:58:50 +00001554
1555func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
1556 if MeterID == 0 { // This should never happen
1557 log.Error("Invalid meter id")
1558 return "", errors.New("invalid meter id")
1559 }
1560 if Dir == tp_pb.Direction_UPSTREAM {
1561 return "upstream", nil
1562 } else if Dir == tp_pb.Direction_DOWNSTREAM {
1563 return "downstream", nil
1564 }
1565 return "", nil
1566}
1567
1568func (f *OpenOltFlowMgr) checkAndAddFlow(args map[string]uint32, classifierInfo map[string]interface{},
1569 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, gemPort, intfID, onuID, uniID, portNo uint32,
1570 TpInst *tp.TechProfile, allocID []uint32, gemPorts []uint32, TpID uint32, uni string) {
1571 if ipProto, ok := classifierInfo[IPProto]; ok {
1572 if ipProto.(uint32) == IPProtoDhcp {
1573 log.Info("Adding DHCP flow")
1574 if pcp, ok := classifierInfo[VlanPcp]; ok {
1575 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1576 tp_pb.Direction_UPSTREAM,
1577 pcp.(uint32))
1578 //Adding DHCP upstream flow
1579 f.addDHCPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
1580 } else {
1581 //Adding DHCP upstream flow to all gemports
1582 installFlowOnAllGemports(f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, DhcpFlow)
1583 }
1584
1585 } else if ipProto == IgmpProto {
1586 log.Info("igmp flow add ignored, not implemented yet")
1587 return
1588 } else {
1589 log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
1590 return
1591 }
1592 } else if ethType, ok := classifierInfo[EthType]; ok {
1593 if ethType.(uint32) == EapEthType {
1594 log.Info("Adding EAPOL flow")
1595 var vlanID uint32
1596 if val, ok := classifierInfo[VlanVid]; ok {
1597 vlanID = (val.(uint32)) & VlanvIDMask
1598 } else {
1599 vlanID = DefaultMgmtVlan
1600 }
1601 if pcp, ok := classifierInfo[VlanPcp]; ok {
1602 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1603 tp_pb.Direction_UPSTREAM,
1604 pcp.(uint32))
1605
1606 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID[0], gemPort, vlanID)
1607 } else {
1608 installFlowOnAllGemports(nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, EapolFlow, vlanID)
1609 }
1610 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001611 } else if _, ok := actionInfo[PushVlan]; ok {
1612 log.Info("Adding upstream data rule")
1613 if pcp, ok := classifierInfo[VlanPcp]; ok {
1614 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1615 tp_pb.Direction_UPSTREAM,
1616 pcp.(uint32))
1617 //Adding HSIA upstream flow
1618 f.addUpstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
1619 } else {
1620 //Adding HSIA upstream flow to all gemports
1621 installFlowOnAllGemports(f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1622 }
1623 } else if _, ok := actionInfo[PopVlan]; ok {
1624 log.Info("Adding Downstream data rule")
1625 if pcp, ok := classifierInfo[VlanPcp]; ok {
1626 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05001627 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001628 pcp.(uint32))
1629 //Adding HSIA downstream flow
1630 f.addDownstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
1631 } else {
1632 //Adding HSIA downstream flow to all gemports
1633 installFlowOnAllGemports(f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1634 }
1635 } else {
1636 log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
1637 return
1638 }
1639 // Send Techprofile download event to child device in go routine as it takes time
1640 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, TpID)
1641}
1642
1643func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
1644 for _, field := range utils.GetOfbFields(flow) {
1645 if field.Type == utils.ETH_TYPE {
1646 classifierInfo[EthType] = field.GetEthType()
1647 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
1648 } else if field.Type == utils.IP_PROTO {
1649 classifierInfo[IPProto] = field.GetIpProto()
1650 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
1651 } else if field.Type == utils.IN_PORT {
1652 classifierInfo[InPort] = field.GetPort()
1653 log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
1654 } else if field.Type == utils.VLAN_VID {
1655 classifierInfo[VlanVid] = field.GetVlanVid()
1656 log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
1657 } else if field.Type == utils.VLAN_PCP {
1658 classifierInfo[VlanPcp] = field.GetVlanPcp()
1659 log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
1660 } else if field.Type == utils.UDP_DST {
1661 classifierInfo[UDPDst] = field.GetUdpDst()
1662 log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
1663 } else if field.Type == utils.UDP_SRC {
1664 classifierInfo[UDPSrc] = field.GetUdpSrc()
1665 log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
1666 } else if field.Type == utils.IPV4_DST {
1667 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
1668 log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
1669 } else if field.Type == utils.IPV4_SRC {
1670 classifierInfo[Ipv4Src] = field.GetIpv4Src()
1671 log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
1672 } else if field.Type == utils.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001673 classifierInfo[Metadata] = field.GetTableMetadata()
1674 log.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001675 } else if field.Type == utils.TUNNEL_ID {
1676 classifierInfo[TunnelID] = field.GetTunnelId()
1677 log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
1678 } else {
1679 log.Errorw("Un supported field type", log.Fields{"type": field.Type})
1680 return
1681 }
1682 }
1683}
1684
1685func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
1686 for _, action := range utils.GetActions(flow) {
1687 if action.Type == utils.OUTPUT {
1688 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001689 actionInfo[Output] = out.GetPort()
1690 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001691 } else {
1692 log.Error("Invalid output port in action")
1693 return errors.New("invalid output port in action")
1694 }
1695 } else if action.Type == utils.POP_VLAN {
1696 actionInfo[PopVlan] = true
1697 log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
1698 } else if action.Type == utils.PUSH_VLAN {
1699 if out := action.GetPush(); out != nil {
1700 if tpid := out.GetEthertype(); tpid != 0x8100 {
1701 log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
1702 } else {
1703 actionInfo[PushVlan] = true
1704 actionInfo[TPID] = tpid
1705 log.Debugw("action-type-push-vlan",
1706 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
1707 }
1708 }
1709 } else if action.Type == utils.SET_FIELD {
1710 if out := action.GetSetField(); out != nil {
1711 if field := out.GetField(); field != nil {
1712 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
1713 log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
1714 return errors.New("invalid openflow class")
1715 }
1716 /*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
1717 if ofbField := field.GetOfbField(); ofbField != nil {
1718 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
1719 if vlan := ofbField.GetVlanVid(); vlan != 0 {
1720 actionInfo[VlanVid] = vlan & 0xfff
1721 log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
1722 } else {
1723 log.Error("No Invalid vlan id in set vlan-vid action")
1724 }
1725 } else {
1726 log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
1727 }
1728 }
1729 }
1730 }
1731 } else {
1732 log.Errorw("Un supported action type", log.Fields{"type": action.Type})
1733 return errors.New("un supported action type")
1734 }
1735 }
1736 return nil
1737}
1738
1739func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001740 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001741 log.Debug("Controller bound trap flows, getting inport from tunnelid")
1742 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
1743 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
1744 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
1745 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07001746 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 +00001747 } else {
1748 log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1749 return errors.New("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1750 }
1751 }
1752 } else {
1753 log.Debug("Non-Controller flows, getting uniport from tunnelid")
1754 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07001755 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001756 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001757 actionInfo[Output] = uniPort
1758 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 +00001759 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001760 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 +00001761 return errors.New("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid")
1762 }
1763 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
1764 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
1765 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
1766 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07001767 log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[Output].(uint32),
1768 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001769 } else {
1770 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 -07001771 "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001772 return errors.New("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid")
1773 }
1774 }
1775 }
1776 return nil
1777}