blob: d47e716cf2bec22587ec1ed00e04ebfd2305d95d [file] [log] [blame]
manikkaraj kbf256be2019-03-25 00:13:48 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070017//Package adaptercore provides the utility for olt devices, flows and statistics
manikkaraj kbf256be2019-03-25 00:13:48 +053018package adaptercore
19
20import (
21 "context"
22 "crypto/md5"
23 "encoding/json"
24 "errors"
25 "fmt"
Manikkaraj kb1d51442019-07-23 10:41:02 -040026 "math/big"
27
manikkaraj kbf256be2019-03-25 00:13:48 +053028 "github.com/opencord/voltha-go/common/log"
29 tp "github.com/opencord/voltha-go/common/techprofile"
Matt Jeannereta93dbed2019-05-17 12:40:05 -040030 "github.com/opencord/voltha-go/rw_core/utils"
Manikkaraj k884c1242019-04-11 16:26:42 +053031 rsrcMgr "github.com/opencord/voltha-openolt-adapter/adaptercore/resourcemanager"
manikkaraj k17652a72019-05-06 09:06:36 -040032 ic "github.com/opencord/voltha-protos/go/inter_container"
manikkaraj kbf256be2019-03-25 00:13:48 +053033 ofp "github.com/opencord/voltha-protos/go/openflow_13"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070034 openoltpb2 "github.com/opencord/voltha-protos/go/openolt"
Manikkaraj kb1d51442019-07-23 10:41:02 -040035 tp_pb "github.com/opencord/voltha-protos/go/tech_profile"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070036 "github.com/opencord/voltha-protos/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040037
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -040038 //deepcopy "github.com/getlantern/deepcopy"
Daniele Rossi22db98e2019-07-11 11:50:00 +000039 "google.golang.org/grpc/codes"
40 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053041)
42
43const (
44 // Flow categories
manikkaraj kbf256be2019-03-25 00:13:48 +053045
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070046 //HsiaFlow flow category
47 HsiaFlow = "HSIA_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053048
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070049 //EapolFlow flow category
50 EapolFlow = "EAPOL_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053051
Manikkaraj kb1d51442019-07-23 10:41:02 -040052 //DhcpFlow flow category
53 DhcpFlow = "DHCP_FLOW"
54
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070055 //IPProtoDhcp flow category
56 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053057
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070058 //IPProtoIgmp flow category
59 IPProtoIgmp = 2
60
61 //EapEthType eapethtype value
62 EapEthType = 0x888e
63 //LldpEthType lldp ethtype value
64 LldpEthType = 0x88cc
65
66 //IgmpProto proto value
67 IgmpProto = 2
manikkaraj kbf256be2019-03-25 00:13:48 +053068
69 //FIXME - see also BRDCM_DEFAULT_VLAN in broadcom_onu.py
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070070
71 //DefaultMgmtVlan default vlan value
72 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053073
manikkaraj kbf256be2019-03-25 00:13:48 +053074 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070075
76 //UPSTREAM constant
77 UPSTREAM = "upstream"
78 //DOWNSTREAM constant
79 DOWNSTREAM = "downstream"
80 //PacketTagType constant
81 PacketTagType = "pkt_tag_type"
82 //UNTAGGED constant
83 UNTAGGED = "untagged"
84 //SingleTag constant
85 SingleTag = "single_tag"
86 //DoubleTag constant
87 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053088
89 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070090
91 //EthType constant
92 EthType = "eth_type"
93 //TPID constant
94 TPID = "tpid"
95 //IPProto constant
96 IPProto = "ip_proto"
97 //InPort constant
98 InPort = "in_port"
99 //VlanVid constant
100 VlanVid = "vlan_vid"
101 //VlanPcp constant
102 VlanPcp = "vlan_pcp"
103
104 //UDPDst constant
105 UDPDst = "udp_dst"
106 //UDPSrc constant
107 UDPSrc = "udp_src"
108 //Ipv4Dst constant
109 Ipv4Dst = "ipv4_dst"
110 //Ipv4Src constant
111 Ipv4Src = "ipv4_src"
112 //METADATA constant
113 METADATA = "metadata"
114 //TunnelID constant
115 TunnelID = "tunnel_id"
116 //OUTPUT constant
117 OUTPUT = "output"
118 // Actions
119
120 //PopVlan constant
121 PopVlan = "pop_vlan"
122 //PushVlan constant
123 PushVlan = "push_vlan"
124 //TrapToHost constant
125 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400126 //MaxMeterBand constant
127 MaxMeterBand = 2
128 //VlanPCPMask contant
129 VlanPCPMask = 0xFF
130 //VlanvIDMask constant
131 VlanvIDMask = 0xFFF
132 //MaxPonPorts constant
133 MaxPonPorts = 16
manikkaraj kbf256be2019-03-25 00:13:48 +0530134)
135
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400136type onuInfo struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700137 intfID uint32
138 onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400139 serialNumber string
140}
141
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700142type onuIDKey struct {
143 intfID uint32
144 onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400145}
146
147type gemPortKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700148 intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400149 gemPort uint32
150}
151
152type packetInInfoKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700153 intfID uint32
154 onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400155 logicalPort uint32
156}
157
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700158//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530159type OpenOltFlowMgr struct {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400160 techprofile []*tp.TechProfileMgr
161 deviceHandler *DeviceHandler
162 resourceMgr *rsrcMgr.OpenOltResourceMgr
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700163 onuIds map[onuIDKey]onuInfo //OnuId -> OnuInfo
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400164 onuSerialNumbers map[string]onuInfo //onu serial_number (string) -> OnuInfo
165 onuGemPortIds map[gemPortKey]onuInfo //GemPortId -> OnuInfo
166 packetInGemPort map[packetInInfoKey]uint32 //packet in gem port
167 storedDeviceFlows []ofp.OfpFlowStats /* Required during deletion to obtain device flows from logical flows */
manikkaraj kbf256be2019-03-25 00:13:48 +0530168}
169
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700170//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
manikkaraj kbf256be2019-03-25 00:13:48 +0530171func NewFlowManager(dh *DeviceHandler, rsrcMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
172 log.Info("Initializing flow manager")
173 var flowMgr OpenOltFlowMgr
174 flowMgr.deviceHandler = dh
175 flowMgr.resourceMgr = rsrcMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400176 flowMgr.techprofile = make([]*tp.TechProfileMgr, MaxPonPorts)
manikkaraj kbf256be2019-03-25 00:13:48 +0530177 if err := flowMgr.populateTechProfilePerPonPort(); err != nil {
178 log.Error("Error while populating tech profile mgr\n")
179 return nil
180 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700181 flowMgr.onuIds = make(map[onuIDKey]onuInfo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400182 flowMgr.onuSerialNumbers = make(map[string]onuInfo)
183 flowMgr.onuGemPortIds = make(map[gemPortKey]onuInfo)
184 flowMgr.packetInGemPort = make(map[packetInInfoKey]uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530185 log.Info("Initialization of flow manager success!!")
186 return &flowMgr
187}
188
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700189func (f *OpenOltFlowMgr) generateStoredFlowID(flowID uint32, direction string) (uint64, error) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400190 if direction == UPSTREAM {
191 log.Debug("upstream flow, shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700192 return 0x1<<15 | uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400193 } else if direction == DOWNSTREAM {
194 log.Debug("downstream flow, not shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700195 return uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400196 } else {
197 log.Debug("Unrecognized direction")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700198 return 0, fmt.Errorf("unrecognized direction %s", direction)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400199 }
200}
201
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700202func (f *OpenOltFlowMgr) registerFlow(flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400203 log.Debug("Registering Flow for Device ", log.Fields{"flow": flowFromCore},
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700204 log.Fields{"device": f.deviceHandler.deviceID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400205
206 var storedFlow ofp.OfpFlowStats
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700207 storedFlow.Id, _ = f.generateStoredFlowID(deviceFlow.FlowId, deviceFlow.FlowType)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400208 log.Debug(fmt.Sprintf("Generated stored device flow. id = %d, flowId = %d, direction = %s", storedFlow.Id,
209 deviceFlow.FlowId, deviceFlow.FlowType))
210 storedFlow.Cookie = flowFromCore.Id
211 f.storedDeviceFlows = append(f.storedDeviceFlows, storedFlow)
212 log.Debugw("updated Stored flow info", log.Fields{"storedDeviceFlows": f.storedDeviceFlows})
213}
214
salmansiddiqui7ac62132019-08-22 03:58:50 +0000215func (f *OpenOltFlowMgr) divideAndAddFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32,
216 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
217 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) {
218 var allocID []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530219 var gemPorts []uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400220 var gemPort uint32
221 var TpInst *tp.TechProfile
manikkaraj kbf256be2019-03-25 00:13:48 +0530222
Manikkaraj kb1d51442019-07-23 10:41:02 -0400223 log.Infow("Dividing flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "portNo": portNo,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000224 "classifier": classifierInfo, "action": actionInfo, "UsMeterID": UsMeterID, "DsMeterID": DsMeterID, "TpID": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400225 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
226 // is because the flow is an NNI flow and there would be no onu resources associated with it
227 // TODO: properly deal with NNI flows
Manikkaraj kb1d51442019-07-23 10:41:02 -0400228 if onuID <= 0 {
Matt Jeanneret77199612019-07-26 18:08:35 -0400229 log.Errorw("No onu id for flow", log.Fields{"portNo": portNo, "classifer": classifierInfo, "action": actionInfo})
manikkaraj kbf256be2019-03-25 00:13:48 +0530230 return
231 }
232
Manikkaraj kb1d51442019-07-23 10:41:02 -0400233 uni := getUniPortPath(intfID, onuID, uniID)
234 log.Debugw("Uni port name", log.Fields{"uni": uni})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000235 allocID, gemPorts, TpInst = f.createTcontGemports(intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
236 if allocID == nil || gemPorts == nil || TpInst == nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400237 log.Error("alloc-id-gem-ports-tp-unavailable")
238 return
239 }
240
241 /* Flows can be added specific to gemport if p-bits are received.
242 * If no pbit mentioned then adding flows for all gemports
manikkaraj kbf256be2019-03-25 00:13:48 +0530243 */
Manikkaraj kb1d51442019-07-23 10:41:02 -0400244
245 args := make(map[string]uint32)
246 args["intfId"] = intfID
247 args["onuId"] = onuID
248 args["uniId"] = uniID
249 args["portNo"] = portNo
salmansiddiqui7ac62132019-08-22 03:58:50 +0000250 args["allocId"] = allocID[0]
Manikkaraj kb1d51442019-07-23 10:41:02 -0400251
salmansiddiqui7ac62132019-08-22 03:58:50 +0000252 f.checkAndAddFlow(args, classifierInfo, actionInfo, flow, gemPort, intfID, onuID, uniID, portNo, TpInst, allocID, gemPorts, TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530253}
254
salmansiddiqui7ac62132019-08-22 03:58:50 +0000255// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
256func (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 -0400257
salmansiddiqui7ac62132019-08-22 03:58:50 +0000258 log.Debugw("CreateSchedulerQueues", log.Fields{"Dir": Dir, "IntfID": IntfID, "OnuID": OnuID,
259 "UniID": UniID, "MeterID": MeterID, "TpInst": *TpInst, "flowMetadata": flowMetadata})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400260
salmansiddiqui7ac62132019-08-22 03:58:50 +0000261 Direction, err := verifyMeterIDAndGetDirection(MeterID, Dir)
262 if err != nil {
263 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400264 }
265
266 /* Lets make a simple assumption that if the meter-id is present on the KV store,
267 * then the scheduler and queues configuration is applied on the OLT device
268 * in the given direction.
269 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000270
Manikkaraj kb1d51442019-07-23 10:41:02 -0400271 var SchedCfg *tp_pb.SchedulerConfig
salmansiddiqui7ac62132019-08-22 03:58:50 +0000272 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(Direction, IntfID, OnuID, UniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400273 if err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000274 log.Error("Failed to get meter for intf %d, onuid %d, uniid %d", IntfID, OnuID, UniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400275 return err
276 }
277 if KvStoreMeter != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000278 if KvStoreMeter.MeterId == MeterID {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400279 log.Debug("Scheduler already created for upstream")
280 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400281 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000282 log.Errorw("Dynamic meter update not supported", log.Fields{"KvStoreMeterId": KvStoreMeter.MeterId, "MeterID-in-flow": MeterID})
283 return errors.New("invalid-meter-id-in-flow")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400284 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000285 log.Debugw("Meter-does-not-exist-Creating-new", log.Fields{"MeterID": MeterID, "Direction": Direction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400286 if Dir == tp_pb.Direction_UPSTREAM {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000287 SchedCfg = f.techprofile[IntfID].GetUsScheduler(TpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400288 } else if Dir == tp_pb.Direction_DOWNSTREAM {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000289 SchedCfg = f.techprofile[IntfID].GetDsScheduler(TpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400290 }
291 var meterConfig *ofp.OfpMeterConfig
292 if flowMetadata != nil {
293 for _, meter := range flowMetadata.Meters {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000294 if MeterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400295 meterConfig = meter
296 log.Debugw("Found-meter-config-from-flowmetadata", log.Fields{"meterConfig": meterConfig})
297 break
298 }
299 }
300 } else {
301 log.Error("Flow-metadata-is-not-present-in-flow")
302 }
303 if meterConfig == nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000304 log.Errorw("Could-not-get-meterbands-from-flowMetadata", log.Fields{"flowMetadata": flowMetadata, "MeterID": MeterID})
305 return errors.New("failed-to-get-meter-from-flowMetadata")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400306 } else if len(meterConfig.Bands) < MaxMeterBand {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000307 log.Errorw("Invalid-number-of-bands-in-meter", log.Fields{"Bands": meterConfig.Bands, "MeterID": MeterID})
308 return errors.New("invalid-number-of-bands-in-meter")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400309 }
310 cir := meterConfig.Bands[0].Rate
311 cbs := meterConfig.Bands[0].BurstSize
312 eir := meterConfig.Bands[1].Rate
313 ebs := meterConfig.Bands[1].BurstSize
314 pir := cir + eir
315 pbs := cbs + ebs
316 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
317
salmansiddiqui7ac62132019-08-22 03:58:50 +0000318 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[IntfID].GetTrafficScheduler(TpInst, SchedCfg, TrafficShaping)}
Manikkaraj kb1d51442019-07-23 10:41:02 -0400319
320 log.Debugw("Sending Traffic scheduler create to device", log.Fields{"Direction": Direction, "TrafficScheds": TrafficSched})
321 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
salmansiddiqui7ac62132019-08-22 03:58:50 +0000322 IntfId: IntfID, OnuId: OnuID,
323 UniId: UniID, PortNo: UniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400324 TrafficScheds: TrafficSched}); err != nil {
325 log.Errorw("Failed to create traffic schedulers", log.Fields{"error": err})
326 return err
327 }
328 // On receiving the CreateTrafficQueues request, the driver should create corresponding
329 // downstream queues.
salmansiddiqui7ac62132019-08-22 03:58:50 +0000330 trafficQueues := f.techprofile[IntfID].GetTrafficQueues(TpInst, Dir)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400331 log.Debugw("Sending Traffic Queues create to device", log.Fields{"Direction": Direction, "TrafficQueues": trafficQueues})
332 if _, err := f.deviceHandler.Client.CreateTrafficQueues(context.Background(),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000333 &tp_pb.TrafficQueues{IntfId: IntfID, OnuId: OnuID,
334 UniId: UniID, PortNo: UniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400335 TrafficQueues: trafficQueues}); err != nil {
336 log.Errorw("Failed to create traffic queues in device", log.Fields{"error": err})
337 return err
338 }
339
salmansiddiqui7ac62132019-08-22 03:58:50 +0000340 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400341 * store the meter id on the KV store, for further reference.
342 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000343 if err := f.resourceMgr.UpdateMeterIDForOnu(Direction, IntfID, OnuID, UniID, meterConfig); err != nil {
344 log.Error("Failed to update meter id for onu %d, meterid %d", OnuID, MeterID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400345 return err
346 }
347 log.Debugw("updated-meter-info into KV store successfully", log.Fields{"Direction": Direction,
348 "Meter": meterConfig})
349 return nil
350}
351
salmansiddiqui7ac62132019-08-22 03:58:50 +0000352// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
353func (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 -0400354
355 var Direction string
356 var SchedCfg *tp_pb.SchedulerConfig
357 var err error
salmansiddiqui7ac62132019-08-22 03:58:50 +0000358 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 -0400359 if Dir == tp_pb.Direction_UPSTREAM {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000360 SchedCfg = f.techprofile[IntfID].GetUsScheduler(TpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400361 Direction = "upstream"
362 } else if Dir == tp_pb.Direction_DOWNSTREAM {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000363 SchedCfg = f.techprofile[IntfID].GetDsScheduler(TpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400364 Direction = "downstream"
365 }
366
salmansiddiqui7ac62132019-08-22 03:58:50 +0000367 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(Direction, IntfID, OnuID, UniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400368 if err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000369 log.Errorf("Failed to get Meter for Onu %d", OnuID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400370 return err
371 }
372 if KVStoreMeter == nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000373 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 -0400374 return nil
375 }
376 cir := KVStoreMeter.Bands[0].Rate
377 cbs := KVStoreMeter.Bands[0].BurstSize
378 eir := KVStoreMeter.Bands[1].Rate
379 ebs := KVStoreMeter.Bands[1].BurstSize
380 pir := cir + eir
381 pbs := cbs + ebs
382
383 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
384
salmansiddiqui7ac62132019-08-22 03:58:50 +0000385 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[IntfID].GetTrafficScheduler(TpInst, SchedCfg, TrafficShaping)}
386 TrafficQueues := f.techprofile[IntfID].GetTrafficQueues(TpInst, Dir)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400387
388 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(context.Background(),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000389 &tp_pb.TrafficQueues{IntfId: IntfID, OnuId: OnuID,
390 UniId: UniID, PortNo: UniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400391 TrafficQueues: TrafficQueues}); err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000392 log.Errorw("Failed to remove traffic queues", log.Fields{"error": err})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400393 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400394 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000395 log.Debug("Removed traffic queues successfully")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400396 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
salmansiddiqui7ac62132019-08-22 03:58:50 +0000397 IntfId: IntfID, OnuId: OnuID,
398 UniId: UniID, PortNo: UniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400399 TrafficScheds: TrafficSched}); err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000400 log.Errorw("failed to remove traffic schedulers", log.Fields{"error": err})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400401 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400402 }
403
salmansiddiqui7ac62132019-08-22 03:58:50 +0000404 log.Debug("Removed traffic schedulers successfully")
405
406 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400407 * delete the meter id on the KV store.
408 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000409 err = f.resourceMgr.RemoveMeterIDForOnu(Direction, IntfID, OnuID, UniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400410 if err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000411 log.Errorf("Failed to remove meter for onu %d, meter id %d", OnuID, KVStoreMeter.MeterId)
412 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400413 }
414 log.Debugw("Removed-meter-from-KV-store successfully", log.Fields{"MeterId": KVStoreMeter.MeterId, "dir": Direction})
415 return err
416}
417
manikkaraj kbf256be2019-03-25 00:13:48 +0530418// This function allocates tconts and GEM ports for an ONU, currently one TCONT is supported per ONU
Manikkaraj kb1d51442019-07-23 10:41:02 -0400419func (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 +0530420 var allocID []uint32
421 var gemPortIDs []uint32
422 //If we already have allocated earlier for this onu, render them
salmansiddiqui7ac62132019-08-22 03:58:50 +0000423 if tcontID := f.resourceMgr.GetCurrentAllocIDForOnu(intfID, onuID, uniID); tcontID != 0 {
424 allocID = append(allocID, tcontID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530425 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700426 gemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400427
428 tpPath := f.getTPpath(intfID, uni, TpID)
429 // Check tech profile instance already exists for derived port name
salmansiddiqui7ac62132019-08-22 03:58:50 +0000430 techProfileInstance, err := f.techprofile[intfID].GetTPInstanceFromKVStore(TpID, tpPath)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400431 if err != nil { // This should not happen, something wrong in KV backend transaction
432 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": TpID, "path": tpPath})
433 return nil, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530434 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400435
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700436 log.Debug("Creating New TConts and Gem ports", log.Fields{"pon": intfID, "onu": onuID, "uni": uniID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530437
salmansiddiqui7ac62132019-08-22 03:58:50 +0000438 if techProfileInstance == nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530439 log.Info("Creating tech profile instance", log.Fields{"path": tpPath})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000440 techProfileInstance = f.techprofile[intfID].CreateTechProfInstance(TpID, uni, intfID)
441 if techProfileInstance == nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530442 log.Error("Tech-profile-instance-creation-failed")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400443 return nil, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530444 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000445 f.resourceMgr.UpdateTechProfileIDForOnu(intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530446 } else {
447 log.Debugw("Tech-profile-instance-already-exist-for-given port-name", log.Fields{"uni": uni})
448 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400449 if UsMeterID != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000450 if err := f.CreateSchedulerQueues(tp_pb.Direction_UPSTREAM, intfID, onuID, uniID, uniPort, techProfileInstance, UsMeterID, flowMetadata); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400451 log.Errorw("CreateSchedulerQueues Failed-upstream", log.Fields{"error": err, "meterID": UsMeterID})
452 return nil, nil, nil
453 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530454 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400455 if DsMeterID != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000456 if err := f.CreateSchedulerQueues(tp_pb.Direction_DOWNSTREAM, intfID, onuID, uniID, uniPort, techProfileInstance, DsMeterID, flowMetadata); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400457 log.Errorw("CreateSchedulerQueues Failed-downstream", log.Fields{"error": err, "meterID": DsMeterID})
458 return nil, nil, nil
459 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530460 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400461 if len(allocID) == 0 { // Created TCONT first time
salmansiddiqui7ac62132019-08-22 03:58:50 +0000462 allocID = append(allocID, techProfileInstance.UsScheduler.AllocID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400463 }
464 if len(gemPortIDs) == 0 { // Create GEM ports first time
salmansiddiqui7ac62132019-08-22 03:58:50 +0000465 for _, gem := range techProfileInstance.UpstreamGemPortAttributeList {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400466 gemPortIDs = append(gemPortIDs, gem.GemportID)
467 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530468 }
469 log.Debugw("Allocated Tcont and GEM ports", log.Fields{"allocID": allocID, "gemports": gemPortIDs})
470 // Send Tconts and GEM ports to KV store
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700471 f.storeTcontsGEMPortsIntoKVStore(intfID, onuID, uniID, allocID, gemPortIDs)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000472 return allocID, gemPortIDs, techProfileInstance
manikkaraj kbf256be2019-03-25 00:13:48 +0530473}
474
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700475func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530476
477 log.Debugw("Storing allocated Tconts and GEM ports into KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700478 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "allocID": allocID, "gemPortIDs": gemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530479 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700480 if err := f.resourceMgr.UpdateAllocIdsForOnu(intfID, onuID, uniID, allocID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530481 log.Error("Errow while uploading allocID to KV store")
482 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700483 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(intfID, onuID, uniID, gemPortIDs); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530484 log.Error("Errow while uploading GEMports to KV store")
485 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700486 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(gemPortIDs, intfID, onuID, uniID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530487 log.Error("Errow while uploading gemtopon map to KV store")
488 }
489 log.Debug("Stored tconts and GEM into KV store successfully")
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400490 for _, gemPort := range gemPortIDs {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700491 f.addGemPortToOnuInfoMap(intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400492 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530493}
494
495func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000496 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530497 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000498 for _, intfID := range techRange.IntfIds {
499 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400500 tpCount++
salmansiddiqui7ac62132019-08-22 03:58:50 +0000501 log.Debugw("Init tech profile done", log.Fields{"intfID": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530502 }
503 }
504 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400505 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530506 log.Errorw("Error while populating techprofile",
Manikkaraj kb1d51442019-07-23 10:41:02 -0400507 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000508 return errors.New("error while populating techprofile mgrs")
manikkaraj kbf256be2019-03-25 00:13:48 +0530509 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400510 log.Infow("Populated techprofile for ponports successfully",
511 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
manikkaraj kbf256be2019-03-25 00:13:48 +0530512 return nil
513}
514
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700515func (f *OpenOltFlowMgr) addUpstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530516 portNo uint32, uplinkClassifier map[string]interface{},
517 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700518 allocID uint32, gemportID uint32) {
519 uplinkClassifier[PacketTagType] = SingleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530520 log.Debugw("Adding upstream data flow", log.Fields{"uplinkClassifier": uplinkClassifier, "uplinkAction": uplinkAction})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700521 f.addHSIAFlow(intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
522 UPSTREAM, logicalFlow, allocID, gemportID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530523 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530524}
525
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700526func (f *OpenOltFlowMgr) addDownstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530527 portNo uint32, downlinkClassifier map[string]interface{},
528 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700529 allocID uint32, gemportID uint32) {
530 downlinkClassifier[PacketTagType] = DoubleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530531 log.Debugw("Adding downstream data flow", log.Fields{"downlinkClassifier": downlinkClassifier,
532 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400533 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
534 if vlan, exists := downlinkClassifier[VlanVid]; exists {
535 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
536 if metadata, exists := downlinkClassifier[METADATA]; exists { // inport is filled in metadata by core
537 if uint32(metadata.(uint64)) == MkUniPortNum(intfID, onuID, uniID) {
538 log.Infow("Ignoring DL trap device flow from core", log.Fields{"flow": logicalFlow})
539 return
540 }
541 }
542 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530543 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400544
Manikkaraj k884c1242019-04-11 16:26:42 +0530545 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700546 downlinkAction[PopVlan] = true
547 downlinkAction[VlanVid] = downlinkClassifier[VlanVid]
548 f.addHSIAFlow(intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
549 DOWNSTREAM, logicalFlow, allocID, gemportID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530550}
551
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700552func (f *OpenOltFlowMgr) addHSIAFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +0530553 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700554 allocID uint32, gemPortID uint32) {
Manikkaraj k884c1242019-04-11 16:26:42 +0530555 /* One of the OLT platform (Broadcom BAL) requires that symmetric
556 flows require the same flow_id to be used across UL and DL.
557 Since HSIA flow is the only symmetric flow currently, we need to
558 re-use the flow_id across both direction. The 'flow_category'
559 takes priority over flow_cookie to find any available HSIA_FLOW
560 id for the ONU.
561 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700562 log.Debugw("Adding HSIA flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "classifier": classifier,
563 "action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530564 "logicalFlow": *logicalFlow})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000565 var vlanPit uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400566 if _, ok := classifier[VlanPcp]; ok {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000567 vlanPit = classifier[VlanPcp].(uint32)
568 log.Debugw("Found pbit in the flow", log.Fields{"vlan_pit": vlanPit})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400569 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700570 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000571 flowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, HsiaFlow, vlanPit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530572 if err != nil {
573 log.Errorw("Flow id unavailable for HSIA flow", log.Fields{"direction": direction})
574 return
575 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700576 var classifierProto *openoltpb2.Classifier
577 var actionProto *openoltpb2.Action
Manikkaraj k884c1242019-04-11 16:26:42 +0530578 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
579 log.Error("Error in making classifier protobuf for hsia flow")
580 return
581 }
582 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
583 if actionProto = makeOpenOltActionField(action); actionProto == nil {
584 log.Errorw("Error in making action protobuf for hsia flow", log.Fields{"direction": direction})
585 return
586 }
587 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700588 networkIntfID := f.deviceHandler.nniIntfID
589 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
590 OnuId: int32(onuID),
591 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000592 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530593 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700594 AllocId: int32(allocID),
595 NetworkIntfId: int32(networkIntfID),
596 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530597 Classifier: classifierProto,
598 Action: actionProto,
599 Priority: int32(logicalFlow.Priority),
600 Cookie: logicalFlow.Cookie,
601 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400602 if ok := f.addFlowToDevice(logicalFlow, &flow); ok {
Manikkaraj k884c1242019-04-11 16:26:42 +0530603 log.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000604 flowsToKVStore := f.getUpdatedFlowInfo(&flow, flowStoreCookie, HsiaFlow, flowID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530605 if err := f.updateFlowInfoToKVStore(flow.AccessIntfId,
606 flow.OnuId,
607 flow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400608 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530609 log.Errorw("Error uploading HSIA flow into KV store", log.Fields{"flow": flow, "direction": direction, "error": err})
610 return
611 }
612 }
613}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700614func (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 +0530615
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700616 var dhcpFlow openoltpb2.Flow
617 var actionProto *openoltpb2.Action
618 var classifierProto *openoltpb2.Classifier
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530619
620 // Clear the action map
621 for k := range action {
622 delete(action, k)
623 }
624
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700625 action[TrapToHost] = true
626 classifier[UDPSrc] = uint32(68)
627 classifier[UDPDst] = uint32(67)
628 classifier[PacketTagType] = SingleTag
629 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530630
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700631 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530632
Manikkaraj kb1d51442019-07-23 10:41:02 -0400633 flowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, "", 0 /*classifier[VLAN_PCP].(uint32)*/)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530634
635 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700636 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530637 return
638 }
639
640 log.Debugw("Creating UL DHCP flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID})
641
642 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
643 log.Error("Error in making classifier protobuf for ul flow")
644 return
645 }
646 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
647 if actionProto = makeOpenOltActionField(action); actionProto == nil {
648 log.Error("Error in making action protobuf for ul flow")
649 return
650 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700651 networkIntfID := f.deviceHandler.nniIntfID
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530652
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700653 dhcpFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
654 OnuId: int32(onuID),
655 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530656 FlowId: flowID,
657 FlowType: UPSTREAM,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700658 AllocId: int32(allocID),
659 NetworkIntfId: int32(networkIntfID),
660 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530661 Classifier: classifierProto,
662 Action: actionProto,
663 Priority: int32(logicalFlow.Priority),
664 Cookie: logicalFlow.Cookie,
665 PortNo: portNo}
666
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400667 if ok := f.addFlowToDevice(logicalFlow, &dhcpFlow); ok {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530668 log.Debug("DHCP UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400669 flowsToKVStore := f.getUpdatedFlowInfo(&dhcpFlow, flowStoreCookie, "DHCP", flowID)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530670 if err := f.updateFlowInfoToKVStore(dhcpFlow.AccessIntfId,
671 dhcpFlow.OnuId,
672 dhcpFlow.UniId,
673 dhcpFlow.FlowId, flowsToKVStore); err != nil {
674 log.Errorw("Error uploading DHCP UL flow into KV store", log.Fields{"flow": dhcpFlow, "error": err})
675 return
676 }
677 }
678
manikkaraj kbf256be2019-03-25 00:13:48 +0530679 return
680}
681
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700682// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
683func (f *OpenOltFlowMgr) addEAPOLFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, vlanID uint32) {
684 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 +0530685
686 uplinkClassifier := make(map[string]interface{})
687 uplinkAction := make(map[string]interface{})
688 downlinkClassifier := make(map[string]interface{})
689 downlinkAction := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700690 var upstreamFlow openoltpb2.Flow
691 var downstreamFlow openoltpb2.Flow
manikkaraj kbf256be2019-03-25 00:13:48 +0530692
693 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700694 uplinkClassifier[EthType] = uint32(EapEthType)
695 uplinkClassifier[PacketTagType] = SingleTag
696 uplinkClassifier[VlanVid] = vlanID
manikkaraj kbf256be2019-03-25 00:13:48 +0530697 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700698 uplinkAction[TrapToHost] = true
699 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530700 //Add Uplink EAPOL Flow
Manikkaraj kb1d51442019-07-23 10:41:02 -0400701 uplinkFlowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530702 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700703 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manikkaraj k884c1242019-04-11 16:26:42 +0530704 return
manikkaraj kbf256be2019-03-25 00:13:48 +0530705 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700706 var classifierProto *openoltpb2.Classifier
707 var actionProto *openoltpb2.Action
708 log.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530709
710 if classifierProto = makeOpenOltClassifierField(uplinkClassifier); classifierProto == nil {
711 log.Error("Error in making classifier protobuf for ul flow")
712 return
713 }
714 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
715 if actionProto = makeOpenOltActionField(uplinkAction); actionProto == nil {
716 log.Error("Error in making action protobuf for ul flow")
717 return
718 }
719 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700720 networkIntfID := f.deviceHandler.nniIntfID
721 upstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
722 OnuId: int32(onuID),
723 UniId: int32(uniID),
724 FlowId: uplinkFlowID,
manikkaraj kbf256be2019-03-25 00:13:48 +0530725 FlowType: UPSTREAM,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700726 AllocId: int32(allocID),
727 NetworkIntfId: int32(networkIntfID),
728 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530729 Classifier: classifierProto,
730 Action: actionProto,
731 Priority: int32(logicalFlow.Priority),
732 Cookie: logicalFlow.Cookie,
733 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400734 if ok := f.addFlowToDevice(logicalFlow, &upstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530735 log.Debug("EAPOL UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400736 flowCategory := "EAPOL"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700737 flowsToKVStore := f.getUpdatedFlowInfo(&upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530738 if err := f.updateFlowInfoToKVStore(upstreamFlow.AccessIntfId,
739 upstreamFlow.OnuId,
740 upstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400741 upstreamFlow.FlowId,
742 /* lowCategory, */
743 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530744 log.Errorw("Error uploading EAPOL UL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
745 return
746 }
747 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400748 // Dummy Downstream flow due to BAL 2.6 limitation
749 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530750 /* Add Downstream EAPOL Flow, Only for first EAP flow (BAL
751 # requirement)
752 # On one of the platforms (Broadcom BAL), when same DL classifier
753 # vlan was used across multiple ONUs, eapol flow re-adds after
754 # flow delete (cases of onu reboot/disable) fails.
755 # In order to generate unique vlan, a combination of intf_id
756 # onu_id and uniId is used.
757 # uniId defaults to 0, so add 1 to it.
758 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700759 log.Debugw("Creating DL EAPOL flow with default vlan", log.Fields{"vlan": vlanID})
760 specialVlanDlFlow := 4090 - intfID*onuID*(uniID+1)
manikkaraj kbf256be2019-03-25 00:13:48 +0530761 // Assert that we do not generate invalid vlans under no condition
762 if specialVlanDlFlow <= 2 {
763 log.Fatalw("invalid-vlan-generated", log.Fields{"vlan": specialVlanDlFlow})
764 return
765 }
766 log.Debugw("specialVlanEAPOLDlFlow:", log.Fields{"dl_vlan": specialVlanDlFlow})
767 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700768 downlinkClassifier[PacketTagType] = SingleTag
Manikkaraj kb1d51442019-07-23 10:41:02 -0400769 downlinkClassifier[EthType] = uint32(EapEthType)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700770 downlinkClassifier[VlanVid] = uint32(specialVlanDlFlow)
manikkaraj kbf256be2019-03-25 00:13:48 +0530771 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700772 downlinkAction[PushVlan] = true
773 downlinkAction[VlanVid] = vlanID
774 flowStoreCookie := getFlowStoreCookie(downlinkClassifier, gemPortID)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000775 downlinkFlowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530776 if err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530777 log.Errorw("flowId unavailable for DL EAPOL",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700778 log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
manikkaraj kbf256be2019-03-25 00:13:48 +0530779 return
780 }
781 log.Debugw("Creating DL EAPOL flow",
salmansiddiqui7ac62132019-08-22 03:58:50 +0000782 log.Fields{"dl_classifier": downlinkClassifier, "dl_action": downlinkAction, "downlinkFlowID": downlinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530783 if classifierProto = makeOpenOltClassifierField(downlinkClassifier); classifierProto == nil {
784 log.Error("Error in making classifier protobuf for downlink flow")
785 return
786 }
787 if actionProto = makeOpenOltActionField(downlinkAction); actionProto == nil {
788 log.Error("Error in making action protobuf for dl flow")
789 return
790 }
791 // Downstream flow in grpc protobuf
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700792 downstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
793 OnuId: int32(onuID),
794 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000795 FlowId: downlinkFlowID,
manikkaraj kbf256be2019-03-25 00:13:48 +0530796 FlowType: DOWNSTREAM,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700797 AllocId: int32(allocID),
798 NetworkIntfId: int32(networkIntfID),
799 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530800 Classifier: classifierProto,
801 Action: actionProto,
802 Priority: int32(logicalFlow.Priority),
803 Cookie: logicalFlow.Cookie,
804 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400805 if ok := f.addFlowToDevice(logicalFlow, &downstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530806 log.Debug("EAPOL DL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400807 flowCategory := ""
salmansiddiqui7ac62132019-08-22 03:58:50 +0000808 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamFlow, flowStoreCookie, flowCategory, downlinkFlowID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530809 if err := f.updateFlowInfoToKVStore(downstreamFlow.AccessIntfId,
810 downstreamFlow.OnuId,
811 downstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400812 downstreamFlow.FlowId,
813 /* flowCategory, */
814 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530815 log.Errorw("Error uploading EAPOL DL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
816 return
817 }
818 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530819 }
820 log.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
821}
822
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700823func makeOpenOltClassifierField(classifierInfo map[string]interface{}) *openoltpb2.Classifier {
824 var classifier openoltpb2.Classifier
825 if etherType, ok := classifierInfo[EthType]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530826 classifier.EthType = etherType.(uint32)
827 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700828 if ipProto, ok := classifierInfo[IPProto]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530829 classifier.IpProto = ipProto.(uint32)
830 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700831 if vlanID, ok := classifierInfo[VlanVid]; ok {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400832 classifier.OVid = (vlanID.(uint32)) & VlanvIDMask
manikkaraj kbf256be2019-03-25 00:13:48 +0530833 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400834 if metadata, ok := classifierInfo[METADATA]; ok {
Manikkaraj k884c1242019-04-11 16:26:42 +0530835 classifier.IVid = uint32(metadata.(uint64))
manikkaraj kbf256be2019-03-25 00:13:48 +0530836 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700837 if vlanPcp, ok := classifierInfo[VlanPcp]; ok {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400838 if vlanPcp == 0 {
839 classifier.OPbits = VlanPCPMask
840 } else {
841 classifier.OPbits = (vlanPcp.(uint32)) & VlanPCPMask
842 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530843 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700844 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530845 classifier.SrcPort = udpSrc.(uint32)
846 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700847 if udpDst, ok := classifierInfo[UDPDst]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530848 classifier.DstPort = udpDst.(uint32)
849 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700850 if ipv4Dst, ok := classifierInfo[Ipv4Dst]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530851 classifier.DstIp = ipv4Dst.(uint32)
852 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700853 if ipv4Src, ok := classifierInfo[Ipv4Src]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530854 classifier.SrcIp = ipv4Src.(uint32)
855 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700856 if pktTagType, ok := classifierInfo[PacketTagType]; ok {
857 if pktTagType.(string) == SingleTag {
858 classifier.PktTagType = SingleTag
859 } else if pktTagType.(string) == DoubleTag {
860 classifier.PktTagType = DoubleTag
manikkaraj kbf256be2019-03-25 00:13:48 +0530861 } else if pktTagType.(string) == UNTAGGED {
862 classifier.PktTagType = UNTAGGED
863 } else {
864 log.Error("Invalid tag type in classifier") // should not hit
865 return nil
866 }
867 }
868 return &classifier
869}
870
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700871func makeOpenOltActionField(actionInfo map[string]interface{}) *openoltpb2.Action {
872 var actionCmd openoltpb2.ActionCmd
873 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +0530874 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700875 if _, ok := actionInfo[PopVlan]; ok {
876 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530877 action.Cmd.RemoveOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700878 } else if _, ok := actionInfo[PushVlan]; ok {
879 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530880 action.Cmd.AddOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700881 } else if _, ok := actionInfo[TrapToHost]; ok {
882 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +0530883 } else {
884 log.Errorw("Invalid-action-field", log.Fields{"action": actionInfo})
885 return nil
886 }
887 return &action
888}
889
Manikkaraj kb1d51442019-07-23 10:41:02 -0400890func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uni string, TpID uint32) string {
891 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530892}
893
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700894func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530895 if len(classifier) == 0 { // should never happen
896 log.Error("Invalid classfier object")
897 return 0
898 }
899 var jsonData []byte
900 var flowString string
901 var err error
902 // TODO: Do we need to marshall ??
903 if jsonData, err = json.Marshal(classifier); err != nil {
904 log.Error("Failed to encode classifier")
905 return 0
906 }
907 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700908 if gemPortID != 0 {
909 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +0530910 }
911 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700912 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +0530913 hash := big.NewInt(0)
914 hash.SetBytes(h.Sum(nil))
915 return hash.Uint64()
916}
917
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700918func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openoltpb2.Flow, flowStoreCookie uint64, flowCategory string, deviceFlowID uint32) *[]rsrcMgr.FlowInfo {
919 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
920 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400921 /* For flows which trap out of the NNI, the AccessIntfId is invalid
922 (set to -1). In such cases, we need to refer to the NetworkIntfId .
923 */
924 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700925 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400926 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700927 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400928 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700929 // Get existing flows matching flowid for given subscriber from KV store
930 existingFlows := f.resourceMgr.GetFlowIDInfo(intfID, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -0400931 if existingFlows != nil {
932 log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700933 //for _, f := range *existingFlows {
934 // flows = append(flows, f)
935 //}
936 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -0400937 }
938 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 +0530939 return &flows
940}
941
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400942//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
943// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
944// var intfId uint32
945// /* For flows which trap out of the NNI, the AccessIntfId is invalid
946// (set to -1). In such cases, we need to refer to the NetworkIntfId .
947// */
948// if flow.AccessIntfId != -1 {
949// intfId = uint32(flow.AccessIntfId)
950// } else {
951// intfId = uint32(flow.NetworkIntfId)
952// }
953// // Get existing flows matching flowid for given subscriber from KV store
954// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
955// if existingFlows != nil {
956// log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
957// for _, f := range *existingFlows {
958// flows = append(flows, f)
959// }
960// }
961// log.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
962// return &flows
963//}
964
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700965func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
manikkaraj k17652a72019-05-06 09:06:36 -0400966 log.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700967 if err := f.resourceMgr.UpdateFlowIDInfo(intfID, onuID, uniID, flowID, flows); err != nil {
manikkaraj k17652a72019-05-06 09:06:36 -0400968 log.Debug("Error while Storing flow into KV store")
969 return err
970 }
971 log.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +0530972 return nil
973}
974
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700975func (f *OpenOltFlowMgr) addFlowToDevice(logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) bool {
Daniele Rossi22db98e2019-07-11 11:50:00 +0000976
977 var intfID uint32
978 /* For flows which trap out of the NNI, the AccessIntfId is invalid
979 (set to -1). In such cases, we need to refer to the NetworkIntfId .
980 */
981 if deviceFlow.AccessIntfId != -1 {
982 intfID = uint32(deviceFlow.AccessIntfId)
983 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400984 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +0000985 intfID = uint32(deviceFlow.NetworkIntfId)
986 }
987
manikkaraj kbf256be2019-03-25 00:13:48 +0530988 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
989 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +0000990
991 st, _ := status.FromError(err)
992 if st.Code() == codes.AlreadyExists {
993 log.Debug("Flow already exixts", log.Fields{"err": err, "deviceFlow": deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +0530994 return false
995 }
Daniele Rossi22db98e2019-07-11 11:50:00 +0000996
997 if err != nil {
998 log.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": deviceFlow})
999 f.resourceMgr.FreeFlowID(intfID, uint32(deviceFlow.OnuId), uint32(deviceFlow.UniId), deviceFlow.FlowId)
1000 return false
1001 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001002 log.Debugw("Flow added to device successfully ", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001003 f.registerFlow(logicalFlow, deviceFlow)
1004 return true
1005}
1006
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001007func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) bool {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001008 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1009 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1010 if err != nil {
1011 log.Errorw("Failed to Remove flow from device", log.Fields{"err": err, "deviceFlow": deviceFlow})
1012 return false
1013 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001014 log.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301015 return true
1016}
1017
1018/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1019 //update core flows_proxy : flows_proxy.update('/', flows)
1020}
1021
1022func generateStoredId(flowId uint32, direction string)uint32{
1023
1024 if direction == UPSTREAM{
1025 log.Debug("Upstream flow shifting flowid")
1026 return ((0x1 << 15) | flowId)
1027 }else if direction == DOWNSTREAM{
1028 log.Debug("Downstream flow not shifting flowid")
1029 return flowId
1030 }else{
1031 log.Errorw("Unrecognized direction",log.Fields{"direction": direction})
1032 return flowId
1033 }
1034}
1035
1036*/
1037
1038func addLLDPFlow(flow *ofp.OfpFlowStats, portNo uint32) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001039 log.Info("unimplemented flow : %v, portNo : %v ", flow, portNo)
manikkaraj kbf256be2019-03-25 00:13:48 +05301040}
1041
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001042func getUniPortPath(intfID uint32, onuID uint32, uniID uint32) string {
1043 return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1044}
1045
1046//getOnuChildDevice to fetch onu
1047func (f *OpenOltFlowMgr) getOnuChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
1048 log.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
1049 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
1050 onuDevice := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301051 if onuDevice == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001052 log.Errorw("onu not found", log.Fields{"intfId": parentPortNo, "onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301053 return nil, errors.New("onu not found")
manikkaraj kbf256be2019-03-25 00:13:48 +05301054 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301055 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1056 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301057}
1058
1059func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001060 log.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301061 return nil
1062}
1063
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001064func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
1065 log.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301066}
1067
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001068func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001069 if id>>15 == 0x1 {
1070 return id & 0x7fff, UPSTREAM
1071 }
1072 return id, DOWNSTREAM
1073}
1074
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001075func (f *OpenOltFlowMgr) clearFlowFromResourceManager(flow *ofp.OfpFlowStats, flowID uint32, flowDirection string) {
1076 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowID": flowID, "flowDirection": flowDirection, "flow": *flow})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001077 portNum, ponIntf, onuID, uniID, err := FlowExtractInfo(flow, flowDirection)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001078 if err != nil {
1079 log.Error(err)
1080 return
1081 }
1082 log.Debugw("Extracted access info from flow to be deleted",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001083 log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001084
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001085 flowsInfo := f.resourceMgr.GetFlowIDInfo(ponIntf, onuID, uniID, flowID)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001086 if flowsInfo == nil {
1087 log.Debugw("No FlowInfo found found in KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001088 log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001089 return
1090 }
1091 var updatedFlows []rsrcMgr.FlowInfo
1092
1093 for _, flow := range *flowsInfo {
1094 updatedFlows = append(updatedFlows, flow)
1095 }
1096
1097 for i, storedFlow := range updatedFlows {
1098 if flowDirection == storedFlow.Flow.FlowType {
1099 //Remove the Flow from FlowInfo
1100 log.Debugw("Removing flow to be deleted", log.Fields{"flow": storedFlow})
1101 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1102 break
1103 }
1104 }
1105
1106 if len(updatedFlows) >= 0 {
1107 // There are still flows referencing the same flow_id.
1108 // So the flow should not be freed yet.
1109 // For ex: Case of HSIA where same flow is shared
1110 // between DS and US.
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001111 f.updateFlowInfoToKVStore(int32(ponIntf), int32(onuID), int32(uniID), flowID, &updatedFlows)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001112 if len(updatedFlows) == 0 {
1113 log.Debugw("Releasing flow Id to resource manager", log.Fields{"ponIntf": ponIntf, "onuId": onuID, "uniId": uniID, "flowId": flowID})
1114 f.resourceMgr.FreeFlowID(ponIntf, onuID, uniID, flowID)
1115 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001116 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001117 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ponIntf, onuID, uniID)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001118 if len(flowIds) == 0 {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001119 log.Debugf("Flow count for subscriber %d is zero", onuID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001120 kvstoreTpID := f.resourceMgr.GetTechProfileIDForOnu(ponIntf, onuID, uniID)
1121 if kvstoreTpID == 0 {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001122 log.Warnw("Could-not-find-techprofile-tableid-for-uni", log.Fields{"ponIntf": ponIntf, "onuId": onuID, "uniId": uniID})
1123 return
1124 }
1125 uni := getUniPortPath(ponIntf, onuID, uniID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001126 tpPath := f.getTPpath(ponIntf, uni, kvstoreTpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001127 log.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001128 techprofileInst, err := f.techprofile[ponIntf].GetTPInstanceFromKVStore(kvstoreTpID, tpPath)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001129 if err != nil { // This should not happen, something wrong in KV backend transaction
1130 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": 20, "path": tpPath})
1131 return
1132 }
1133 if techprofileInst == nil {
1134 log.Errorw("Tech-profile-instance-does-not-exist-in-KV Store", log.Fields{"tpPath": tpPath})
1135 return
1136 }
1137
1138 f.RemoveSchedulerQueues(tp_pb.Direction_UPSTREAM, ponIntf, onuID, uniID, portNum, techprofileInst)
1139 f.RemoveSchedulerQueues(tp_pb.Direction_DOWNSTREAM, ponIntf, onuID, uniID, portNum, techprofileInst)
1140 } else {
1141 log.Debugf("Flow ids for subscriber", log.Fields{"onu": onuID, "flows": flowIds})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001142 }
1143}
1144
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001145//RemoveFlow removes the flow from the device
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001146func (f *OpenOltFlowMgr) RemoveFlow(flow *ofp.OfpFlowStats) {
1147 log.Debugw("Removing Flow", log.Fields{"flow": flow})
1148 var deviceFlowsToRemove []ofp.OfpFlowStats
1149 var deletedFlowsIdx []int
1150 for _, curFlow := range f.storedDeviceFlows {
1151 if curFlow.Cookie == flow.Id {
1152 log.Debugw("Found found matching flow-cookie", log.Fields{"curFlow": curFlow})
1153 deviceFlowsToRemove = append(deviceFlowsToRemove, curFlow)
1154 }
1155 }
1156 log.Debugw("Flows to be deleted", log.Fields{"deviceFlowsToRemove": deviceFlowsToRemove})
1157 for index, curFlow := range deviceFlowsToRemove {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001158 id, direction := f.decodeStoredID(curFlow.GetId())
1159 removeFlowMessage := openoltpb2.Flow{FlowId: uint32(id), FlowType: direction}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001160 if ok := f.removeFlowFromDevice(&removeFlowMessage); ok {
1161 log.Debug("Flow removed from device successfully")
1162 deletedFlowsIdx = append(deletedFlowsIdx, index)
1163 f.clearFlowFromResourceManager(flow, uint32(id), direction) //TODO: Take care of the limitations
1164 }
1165
1166 }
1167 // Can be done in separate go routine as it takes time ?
1168 for _, flowToRemove := range deletedFlowsIdx {
1169 for index, storedFlow := range f.storedDeviceFlows {
1170 if deviceFlowsToRemove[flowToRemove].Cookie == storedFlow.Cookie {
1171 log.Debugw("Removing flow from local Store", log.Fields{"flow": storedFlow})
1172 f.storedDeviceFlows = append(f.storedDeviceFlows[:index], f.storedDeviceFlows[index+1:]...)
1173 break
1174 }
1175 }
1176 }
1177 log.Debugw("Flows removed from the data store",
1178 log.Fields{"number_of_flows_removed": len(deviceFlowsToRemove), "updated_stored_flows": f.storedDeviceFlows})
1179 return
1180}
1181
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001182// AddFlow add flow to device
Manikkaraj kb1d51442019-07-23 10:41:02 -04001183func (f *OpenOltFlowMgr) AddFlow(flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001184 classifierInfo := make(map[string]interface{})
1185 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001186 var UsMeterID uint32
1187 var DsMeterID uint32
1188
1189 log.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001190 formulateClassifierInfoFromFlow(classifierInfo, flow)
1191
1192 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
1193 if err != nil {
1194 // Error logging is already done in the called function
1195 // So just return in case of error
1196 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301197 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001198
manikkaraj k17652a72019-05-06 09:06:36 -04001199 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00001200 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
1201 if err != nil {
1202 // error if any, already logged in the called function
1203 return
manikkaraj k17652a72019-05-06 09:06:36 -04001204 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001205
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001206 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[OUTPUT]})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001207 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[OUTPUT].(uint32))
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001208 if ipProto, ok := classifierInfo[IPProto]; ok {
1209 if ipProto.(uint32) == IPProtoDhcp {
1210 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001211 if udpSrc.(uint32) == uint32(67) {
1212 log.Debug("trap-dhcp-from-nni-flow")
1213 f.addDHCPTrapFlowOnNNI(flow, classifierInfo, portNo)
1214 return
1215 }
1216 }
1217 }
1218 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001219 /* Metadata 8 bytes:
1220 Most Significant 2 Bytes = Inner VLAN
1221 Next 2 Bytes = Tech Profile ID(TPID)
1222 Least Significant 4 Bytes = Port ID
1223 Flow METADATA carries Tech-Profile (TP) ID and is mandatory in all
1224 subscriber related flows.
1225 */
1226 metadata := utils.GetMetadataFromWriteMetadataAction(flow)
1227 if metadata == 0 {
1228 log.Error("Metadata is not present in flow which is mandatory")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001229 return
1230 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001231 TpID := utils.GetTechProfileIDFromWriteMetaData(metadata)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001232 kvstoreTpID := f.resourceMgr.GetTechProfileIDForOnu(intfID, onuID, uniID)
1233 if kvstoreTpID == 0 {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001234 log.Debugf("tpid-not-present-in-kvstore, using tp id %d from flow metadata", TpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001235 } else if kvstoreTpID != uint32(TpID) {
1236 log.Error(" Tech-profile-updates-not-supported", log.Fields{"Tpid-in-flow": TpID, "kvstore-TpId": kvstoreTpID})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001237 return
1238 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001239 log.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001240 if IsUpstream(actionInfo[OUTPUT].(uint32)) {
1241 UsMeterID = utils.GetMeterIdFromFlow(flow)
1242 log.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
1243 } else {
1244 DsMeterID = utils.GetMeterIdFromFlow(flow)
1245 log.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
1246
1247 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001248 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001249}
1250
1251//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04001252func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001253
1254 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301255 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001256 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301257 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301258 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301259 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04001260
Manikkaraj kb1d51442019-07-23 10:41:02 -04001261 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001262 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
manikkaraj k17652a72019-05-06 09:06:36 -04001263 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
1264 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1265 tpDownloadMsg,
1266 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
1267 f.deviceHandler.deviceType,
1268 onuDevice.Type,
1269 onuDevice.Id,
1270 onuDevice.ProxyAddress.DeviceId, "")
1271 if sendErr != nil {
1272 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1273 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1274 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1275 return sendErr
1276 }
1277 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05301278 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301279}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001280
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001281//UpdateOnuInfo function adds onu info to cache
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001282func (f *OpenOltFlowMgr) UpdateOnuInfo(intfID uint32, onuID uint32, serialNum string) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001283 onu := onuInfo{intfID: intfID, onuID: onuID, serialNumber: serialNum}
1284 onuIDkey := onuIDKey{intfID: intfID, onuID: onuID}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001285 f.onuIds[onuIDkey] = onu
1286 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
1287}
1288
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001289//addGemPortToOnuInfoMap function stores adds GEMport to ONU map
1290func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(intfID uint32, onuID uint32, gemPort uint32) {
1291 onuIDkey := onuIDKey{intfID: intfID, onuID: onuID}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001292 if val, ok := f.onuIds[onuIDkey]; ok {
1293 onuInfo := val
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001294 gemportKey := gemPortKey{intfID: intfID, gemPort: gemPort}
1295 f.onuGemPortIds[gemportKey] = onuInfo
1296 log.Debugw("Cached Gemport to Onuinfo map", log.Fields{"GemPort": gemPort, "intfId": onuInfo.intfID, "onuId": onuInfo.onuID})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001297 return
1298 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001299 log.Errorw("OnuInfo not found", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001300}
1301
1302// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001303
1304//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
1305func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
1306 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 -04001307 if serialNumber != "" {
1308 if onuInfo, ok := f.onuSerialNumbers[serialNumber]; ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001309 return onuInfo.onuID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001310 }
1311 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001312 gemportKey := gemPortKey{intfID: intfID, gemPort: gemPortID}
1313 if onuInfo, ok := f.onuGemPortIds[gemportKey]; ok {
1314 log.Debugw("Retrieved onu info from access", log.Fields{"intfId": intfID, "gemPortId": gemPortID, "onuId": onuInfo.onuID})
1315 return onuInfo.onuID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001316 }
1317 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001318 log.Errorw("onuid is not found", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPort": gemPortID})
1319 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 -04001320}
1321
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001322//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
1323func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001324 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001325 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001326 var err error
1327
1328 if packetIn.IntfType == "pon" {
1329 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001330 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001331 log.Errorw("Unable to get ONU ID from GEM/PON port", log.Fields{"pon port": packetIn.IntfId, "gemport": packetIn.GemportId})
1332 return logicalPortNum, err
1333 }
1334 if packetIn.PortNo != 0 {
1335 logicalPortNum = packetIn.PortNo
1336 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001337 uniID := uint32(0) // FIXME - multi-uni support
1338 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001339 }
1340 // 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 -07001341 pktInkey := packetInInfoKey{intfID: packetIn.IntfId, onuID: onuID, logicalPort: logicalPortNum}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001342 f.packetInGemPort[pktInkey] = packetIn.GemportId
1343 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001344 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001345 }
1346 log.Debugw("Retrieved logicalport from packet-in", log.Fields{"logicalPortNum": logicalPortNum, "IntfType": packetIn.IntfType})
1347 return logicalPortNum, nil
1348}
1349
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001350//GetPacketOutGemPortID returns gemPortId
1351func (f *OpenOltFlowMgr) GetPacketOutGemPortID(intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
1352 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001353 var err error
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001354 key := packetInInfoKey{intfID: intfID, onuID: onuID, logicalPort: portNum}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001355 if val, ok := f.packetInGemPort[key]; ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001356 gemPortID = val
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001357 } else {
1358 log.Errorw("Key-Error while fetching packet-out GEM port", log.Fields{"key": key})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001359 err = errors.New("key-error while fetching packet-out GEM port")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001360 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001361 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001362}
1363
Manikkaraj kb1d51442019-07-23 10:41:02 -04001364func installFlowOnAllGemports(
1365 f1 func(intfId uint32, onuId uint32, uniId uint32,
1366 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
1367 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32),
1368 f2 func(intfId uint32, onuId uint32, uniId uint32, portNo uint32,
1369 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32),
1370 args map[string]uint32,
1371 classifier map[string]interface{}, action map[string]interface{},
1372 logicalFlow *ofp.OfpFlowStats,
1373 gemPorts []uint32,
1374 FlowType string,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001375 vlanID ...uint32) {
1376 log.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
1377 for _, gemPortID := range gemPorts {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001378 if FlowType == HsiaFlow || FlowType == DhcpFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001379 f1(args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001380 } else if FlowType == EapolFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001381 f2(args["intfId"], args["onuId"], args["uniId"], args["portNo"], logicalFlow, args["allocId"], gemPortID, vlanID[0])
Manikkaraj kb1d51442019-07-23 10:41:02 -04001382 } else {
1383 log.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
1384 return
1385 }
1386 }
1387}
1388
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001389func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
1390 log.Debug("Adding trap-dhcp-of-nni-flow")
1391 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001392 classifier[PacketTagType] = DoubleTag
1393 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001394 /* We manage flowId resource pool on per PON port basis.
1395 Since this situation is tricky, as a hack, we pass the NNI port
1396 index (network_intf_id) as PON port Index for the flowId resource
1397 pool. Also, there is no ONU Id available for trapping DHCP packets
1398 on NNI port, use onu_id as -1 (invalid)
1399 ****************** CAVEAT *******************
1400 This logic works if the NNI Port Id falls within the same valid
1401 range of PON Port Ids. If this doesn't work for some OLT Vendor
1402 we need to have a re-look at this.
1403 *********************************************
1404 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001405 onuID := -1
1406 uniID := -1
1407 gemPortID := -1
1408 allocID := -1
1409 networkInterfaceID := f.deviceHandler.nniIntfID
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001410 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001411 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), flowStoreCookie); present {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001412 log.Debug("Flow-exists--not-re-adding")
1413 return
1414 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001415 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001416 if err != nil {
1417 log.Errorw("Flow id unavailable for DHCP traponNNI flow", log.Fields{"error": err})
1418 return
1419 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001420 var classifierProto *openoltpb2.Classifier
1421 var actionProto *openoltpb2.Action
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001422 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
1423 log.Error("Error in making classifier protobuf for dhcp trap on nni flow")
1424 return
1425 }
1426 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1427 if actionProto = makeOpenOltActionField(action); actionProto == nil {
1428 log.Error("Error in making action protobuf for dhcp trap on nni flow")
1429 return
1430 }
1431 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001432 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1433 OnuId: int32(onuID), // OnuId not required
1434 UniId: int32(uniID), // UniId not used
1435 FlowId: flowID,
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001436 FlowType: DOWNSTREAM,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001437 AllocId: int32(allocID), // AllocId not used
1438 NetworkIntfId: int32(networkInterfaceID),
1439 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001440 Classifier: classifierProto,
1441 Action: actionProto,
1442 Priority: int32(logicalFlow.Priority),
1443 Cookie: logicalFlow.Cookie,
1444 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001445 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001446 log.Debug("DHCP trap on NNI flow added to device successfully")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001447 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID)
1448 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1449 int32(onuID),
1450 int32(uniID),
1451 flowID, flowsToKVStore); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001452 log.Errorw("Error uploading DHCP DL flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1453 }
1454 }
1455 return
1456}
salmansiddiqui7ac62132019-08-22 03:58:50 +00001457
1458func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
1459 if MeterID == 0 { // This should never happen
1460 log.Error("Invalid meter id")
1461 return "", errors.New("invalid meter id")
1462 }
1463 if Dir == tp_pb.Direction_UPSTREAM {
1464 return "upstream", nil
1465 } else if Dir == tp_pb.Direction_DOWNSTREAM {
1466 return "downstream", nil
1467 }
1468 return "", nil
1469}
1470
1471func (f *OpenOltFlowMgr) checkAndAddFlow(args map[string]uint32, classifierInfo map[string]interface{},
1472 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, gemPort, intfID, onuID, uniID, portNo uint32,
1473 TpInst *tp.TechProfile, allocID []uint32, gemPorts []uint32, TpID uint32, uni string) {
1474 if ipProto, ok := classifierInfo[IPProto]; ok {
1475 if ipProto.(uint32) == IPProtoDhcp {
1476 log.Info("Adding DHCP flow")
1477 if pcp, ok := classifierInfo[VlanPcp]; ok {
1478 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1479 tp_pb.Direction_UPSTREAM,
1480 pcp.(uint32))
1481 //Adding DHCP upstream flow
1482 f.addDHCPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
1483 } else {
1484 //Adding DHCP upstream flow to all gemports
1485 installFlowOnAllGemports(f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, DhcpFlow)
1486 }
1487
1488 } else if ipProto == IgmpProto {
1489 log.Info("igmp flow add ignored, not implemented yet")
1490 return
1491 } else {
1492 log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
1493 return
1494 }
1495 } else if ethType, ok := classifierInfo[EthType]; ok {
1496 if ethType.(uint32) == EapEthType {
1497 log.Info("Adding EAPOL flow")
1498 var vlanID uint32
1499 if val, ok := classifierInfo[VlanVid]; ok {
1500 vlanID = (val.(uint32)) & VlanvIDMask
1501 } else {
1502 vlanID = DefaultMgmtVlan
1503 }
1504 if pcp, ok := classifierInfo[VlanPcp]; ok {
1505 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1506 tp_pb.Direction_UPSTREAM,
1507 pcp.(uint32))
1508
1509 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID[0], gemPort, vlanID)
1510 } else {
1511 installFlowOnAllGemports(nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, EapolFlow, vlanID)
1512 }
1513 }
1514 if ethType == LldpEthType {
1515 log.Info("Adding LLDP flow")
1516 addLLDPFlow(flow, portNo)
1517 return
1518 }
1519 } else if _, ok := actionInfo[PushVlan]; ok {
1520 log.Info("Adding upstream data rule")
1521 if pcp, ok := classifierInfo[VlanPcp]; ok {
1522 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1523 tp_pb.Direction_UPSTREAM,
1524 pcp.(uint32))
1525 //Adding HSIA upstream flow
1526 f.addUpstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
1527 } else {
1528 //Adding HSIA upstream flow to all gemports
1529 installFlowOnAllGemports(f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1530 }
1531 } else if _, ok := actionInfo[PopVlan]; ok {
1532 log.Info("Adding Downstream data rule")
1533 if pcp, ok := classifierInfo[VlanPcp]; ok {
1534 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1535 tp_pb.Direction_UPSTREAM,
1536 pcp.(uint32))
1537 //Adding HSIA downstream flow
1538 f.addDownstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
1539 } else {
1540 //Adding HSIA downstream flow to all gemports
1541 installFlowOnAllGemports(f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1542 }
1543 } else {
1544 log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
1545 return
1546 }
1547 // Send Techprofile download event to child device in go routine as it takes time
1548 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, TpID)
1549}
1550
1551func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
1552 for _, field := range utils.GetOfbFields(flow) {
1553 if field.Type == utils.ETH_TYPE {
1554 classifierInfo[EthType] = field.GetEthType()
1555 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
1556 } else if field.Type == utils.IP_PROTO {
1557 classifierInfo[IPProto] = field.GetIpProto()
1558 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
1559 } else if field.Type == utils.IN_PORT {
1560 classifierInfo[InPort] = field.GetPort()
1561 log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
1562 } else if field.Type == utils.VLAN_VID {
1563 classifierInfo[VlanVid] = field.GetVlanVid()
1564 log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
1565 } else if field.Type == utils.VLAN_PCP {
1566 classifierInfo[VlanPcp] = field.GetVlanPcp()
1567 log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
1568 } else if field.Type == utils.UDP_DST {
1569 classifierInfo[UDPDst] = field.GetUdpDst()
1570 log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
1571 } else if field.Type == utils.UDP_SRC {
1572 classifierInfo[UDPSrc] = field.GetUdpSrc()
1573 log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
1574 } else if field.Type == utils.IPV4_DST {
1575 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
1576 log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
1577 } else if field.Type == utils.IPV4_SRC {
1578 classifierInfo[Ipv4Src] = field.GetIpv4Src()
1579 log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
1580 } else if field.Type == utils.METADATA {
1581 classifierInfo[METADATA] = field.GetTableMetadata()
1582 log.Debug("field-type-metadata", log.Fields{"classifierInfo[METADATA]": classifierInfo[METADATA].(uint64)})
1583 } else if field.Type == utils.TUNNEL_ID {
1584 classifierInfo[TunnelID] = field.GetTunnelId()
1585 log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
1586 } else {
1587 log.Errorw("Un supported field type", log.Fields{"type": field.Type})
1588 return
1589 }
1590 }
1591}
1592
1593func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
1594 for _, action := range utils.GetActions(flow) {
1595 if action.Type == utils.OUTPUT {
1596 if out := action.GetOutput(); out != nil {
1597 actionInfo[OUTPUT] = out.GetPort()
1598 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[OUTPUT].(uint32)})
1599 } else {
1600 log.Error("Invalid output port in action")
1601 return errors.New("invalid output port in action")
1602 }
1603 } else if action.Type == utils.POP_VLAN {
1604 actionInfo[PopVlan] = true
1605 log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
1606 } else if action.Type == utils.PUSH_VLAN {
1607 if out := action.GetPush(); out != nil {
1608 if tpid := out.GetEthertype(); tpid != 0x8100 {
1609 log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
1610 } else {
1611 actionInfo[PushVlan] = true
1612 actionInfo[TPID] = tpid
1613 log.Debugw("action-type-push-vlan",
1614 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
1615 }
1616 }
1617 } else if action.Type == utils.SET_FIELD {
1618 if out := action.GetSetField(); out != nil {
1619 if field := out.GetField(); field != nil {
1620 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
1621 log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
1622 return errors.New("invalid openflow class")
1623 }
1624 /*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
1625 if ofbField := field.GetOfbField(); ofbField != nil {
1626 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
1627 if vlan := ofbField.GetVlanVid(); vlan != 0 {
1628 actionInfo[VlanVid] = vlan & 0xfff
1629 log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
1630 } else {
1631 log.Error("No Invalid vlan id in set vlan-vid action")
1632 }
1633 } else {
1634 log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
1635 }
1636 }
1637 }
1638 }
1639 } else {
1640 log.Errorw("Un supported action type", log.Fields{"type": action.Type})
1641 return errors.New("un supported action type")
1642 }
1643 }
1644 return nil
1645}
1646
1647func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
1648 if isControllerFlow := IsControllerBoundFlow(actionInfo[OUTPUT].(uint32)); isControllerFlow {
1649 log.Debug("Controller bound trap flows, getting inport from tunnelid")
1650 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
1651 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
1652 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
1653 classifierInfo[InPort] = uniPort
1654 log.Debugw("upstream pon-to-controller-flow,inport-in-tunnelid", log.Fields{"newInPort": classifierInfo[InPort].(uint32), "outPort": actionInfo[OUTPUT].(uint32)})
1655 } else {
1656 log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1657 return errors.New("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1658 }
1659 }
1660 } else {
1661 log.Debug("Non-Controller flows, getting uniport from tunnelid")
1662 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
1663 if portType := IntfIDToPortTypeName(actionInfo[OUTPUT].(uint32)); portType == voltha.Port_PON_OLT {
1664 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
1665 actionInfo[OUTPUT] = uniPort
1666 log.Debugw("downstream-nni-to-pon-port-flow, outport-in-tunnelid", log.Fields{"newOutPort": actionInfo[OUTPUT].(uint32), "outPort": actionInfo[OUTPUT].(uint32)})
1667 } else {
1668 log.Debug("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid", log.Fields{"InPort": classifierInfo[InPort].(uint32), "outPort": actionInfo[OUTPUT].(uint32)})
1669 return errors.New("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid")
1670 }
1671 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
1672 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
1673 if uniPort := utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
1674 classifierInfo[InPort] = uniPort
1675 log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[OUTPUT].(uint32),
1676 "outport": actionInfo[OUTPUT].(uint32)})
1677 } else {
1678 log.Debug("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid", log.Fields{"InPort": classifierInfo[InPort].(uint32),
1679 "outPort": actionInfo[OUTPUT].(uint32)})
1680 return errors.New("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid")
1681 }
1682 }
1683 }
1684 return nil
1685}