blob: 63ee91314e4598d22f0003ba0e203576f05efa7d [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"
William Kurkian740a09c2019-10-23 17:07:38 -040027 "sync"
Manikkaraj kb1d51442019-07-23 10:41:02 -040028
Scott Baker51290152019-10-24 14:23:20 -070029 "github.com/opencord/voltha-lib-go/v2/pkg/flows"
30 "github.com/opencord/voltha-lib-go/v2/pkg/log"
31 tp "github.com/opencord/voltha-lib-go/v2/pkg/techprofile"
Manikkaraj k884c1242019-04-11 16:26:42 +053032 rsrcMgr "github.com/opencord/voltha-openolt-adapter/adaptercore/resourcemanager"
serkant.uluderya245caba2019-09-24 23:15:29 -070033 "github.com/opencord/voltha-protos/go/common"
manikkaraj k17652a72019-05-06 09:06:36 -040034 ic "github.com/opencord/voltha-protos/go/inter_container"
manikkaraj kbf256be2019-03-25 00:13:48 +053035 ofp "github.com/opencord/voltha-protos/go/openflow_13"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070036 openoltpb2 "github.com/opencord/voltha-protos/go/openolt"
Manikkaraj kb1d51442019-07-23 10:41:02 -040037 tp_pb "github.com/opencord/voltha-protos/go/tech_profile"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070038 "github.com/opencord/voltha-protos/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040039
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -040040 //deepcopy "github.com/getlantern/deepcopy"
Daniele Rossi22db98e2019-07-11 11:50:00 +000041 "google.golang.org/grpc/codes"
42 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053043)
44
45const (
46 // Flow categories
manikkaraj kbf256be2019-03-25 00:13:48 +053047
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070048 //HsiaFlow flow category
49 HsiaFlow = "HSIA_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053050
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070051 //EapolFlow flow category
52 EapolFlow = "EAPOL_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053053
Manikkaraj kb1d51442019-07-23 10:41:02 -040054 //DhcpFlow flow category
55 DhcpFlow = "DHCP_FLOW"
56
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070057 //IPProtoDhcp flow category
58 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053059
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070060 //IPProtoIgmp flow category
61 IPProtoIgmp = 2
62
63 //EapEthType eapethtype value
64 EapEthType = 0x888e
65 //LldpEthType lldp ethtype value
66 LldpEthType = 0x88cc
67
68 //IgmpProto proto value
69 IgmpProto = 2
manikkaraj kbf256be2019-03-25 00:13:48 +053070
71 //FIXME - see also BRDCM_DEFAULT_VLAN in broadcom_onu.py
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070072
Humera Kouser94d7a842019-08-25 19:04:32 -040073 //ReservedVlan Transparent Vlan
David K. Bainbridge82efc492019-09-04 09:57:11 -070074 ReservedVlan = 4095
Harsh Awasthiea45af72019-08-26 02:39:00 -040075
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070076 //DefaultMgmtVlan default vlan value
77 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053078
manikkaraj kbf256be2019-03-25 00:13:48 +053079 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070080
David K. Bainbridge82efc492019-09-04 09:57:11 -070081 //Upstream constant
82 Upstream = "upstream"
83 //Downstream constant
84 Downstream = "downstream"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070085 //PacketTagType constant
86 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070087 //Untagged constant
88 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070089 //SingleTag constant
90 SingleTag = "single_tag"
91 //DoubleTag constant
92 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053093
94 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070095
96 //EthType constant
97 EthType = "eth_type"
98 //TPID constant
99 TPID = "tpid"
100 //IPProto constant
101 IPProto = "ip_proto"
102 //InPort constant
103 InPort = "in_port"
104 //VlanVid constant
105 VlanVid = "vlan_vid"
106 //VlanPcp constant
107 VlanPcp = "vlan_pcp"
108
109 //UDPDst constant
110 UDPDst = "udp_dst"
111 //UDPSrc constant
112 UDPSrc = "udp_src"
113 //Ipv4Dst constant
114 Ipv4Dst = "ipv4_dst"
115 //Ipv4Src constant
116 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700117 //Metadata constant
118 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700119 //TunnelID constant
120 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700121 //Output constant
122 Output = "output"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700123 // Actions
124
125 //PopVlan constant
126 PopVlan = "pop_vlan"
127 //PushVlan constant
128 PushVlan = "push_vlan"
129 //TrapToHost constant
130 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400131 //MaxMeterBand constant
132 MaxMeterBand = 2
133 //VlanPCPMask contant
134 VlanPCPMask = 0xFF
135 //VlanvIDMask constant
136 VlanvIDMask = 0xFFF
137 //MaxPonPorts constant
138 MaxPonPorts = 16
manikkaraj kbf256be2019-03-25 00:13:48 +0530139)
140
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400141type onuInfo struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700142 intfID uint32
143 onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400144 serialNumber string
145}
146
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700147type onuIDKey struct {
148 intfID uint32
149 onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400150}
151
152type gemPortKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700153 intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400154 gemPort uint32
155}
156
157type packetInInfoKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700158 intfID uint32
159 onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400160 logicalPort uint32
161}
162
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700163//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530164type OpenOltFlowMgr struct {
kdarapub26b4502019-10-05 03:02:33 +0530165 techprofile []tp.TechProfileIf
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400166 deviceHandler *DeviceHandler
167 resourceMgr *rsrcMgr.OpenOltResourceMgr
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700168 onuIds map[onuIDKey]onuInfo //OnuId -> OnuInfo
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400169 onuSerialNumbers map[string]onuInfo //onu serial_number (string) -> OnuInfo
170 onuGemPortIds map[gemPortKey]onuInfo //GemPortId -> OnuInfo
171 packetInGemPort map[packetInInfoKey]uint32 //packet in gem port
172 storedDeviceFlows []ofp.OfpFlowStats /* Required during deletion to obtain device flows from logical flows */
William Kurkian740a09c2019-10-23 17:07:38 -0400173 onuIdsLock sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +0530174}
175
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700176//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
manikkaraj kbf256be2019-03-25 00:13:48 +0530177func NewFlowManager(dh *DeviceHandler, rsrcMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
178 log.Info("Initializing flow manager")
179 var flowMgr OpenOltFlowMgr
180 flowMgr.deviceHandler = dh
181 flowMgr.resourceMgr = rsrcMgr
kdarapub26b4502019-10-05 03:02:33 +0530182 flowMgr.techprofile = make([]tp.TechProfileIf, MaxPonPorts)
manikkaraj kbf256be2019-03-25 00:13:48 +0530183 if err := flowMgr.populateTechProfilePerPonPort(); err != nil {
184 log.Error("Error while populating tech profile mgr\n")
185 return nil
186 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700187 flowMgr.onuIds = make(map[onuIDKey]onuInfo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400188 flowMgr.onuSerialNumbers = make(map[string]onuInfo)
189 flowMgr.onuGemPortIds = make(map[gemPortKey]onuInfo)
190 flowMgr.packetInGemPort = make(map[packetInInfoKey]uint32)
William Kurkian740a09c2019-10-23 17:07:38 -0400191 flowMgr.onuIdsLock = sync.RWMutex{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530192 log.Info("Initialization of flow manager success!!")
193 return &flowMgr
194}
195
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700196func (f *OpenOltFlowMgr) generateStoredFlowID(flowID uint32, direction string) (uint64, error) {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700197 if direction == Upstream {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400198 log.Debug("upstream flow, shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700199 return 0x1<<15 | uint64(flowID), nil
David K. Bainbridge82efc492019-09-04 09:57:11 -0700200 } else if direction == Downstream {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400201 log.Debug("downstream flow, not shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700202 return uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400203 } else {
204 log.Debug("Unrecognized direction")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700205 return 0, fmt.Errorf("unrecognized direction %s", direction)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400206 }
207}
208
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700209func (f *OpenOltFlowMgr) registerFlow(flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400210 log.Debug("Registering Flow for Device ", log.Fields{"flow": flowFromCore},
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700211 log.Fields{"device": f.deviceHandler.deviceID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400212
213 var storedFlow ofp.OfpFlowStats
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700214 storedFlow.Id, _ = f.generateStoredFlowID(deviceFlow.FlowId, deviceFlow.FlowType)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400215 log.Debug(fmt.Sprintf("Generated stored device flow. id = %d, flowId = %d, direction = %s", storedFlow.Id,
216 deviceFlow.FlowId, deviceFlow.FlowType))
217 storedFlow.Cookie = flowFromCore.Id
218 f.storedDeviceFlows = append(f.storedDeviceFlows, storedFlow)
219 log.Debugw("updated Stored flow info", log.Fields{"storedDeviceFlows": f.storedDeviceFlows})
220}
221
salmansiddiqui7ac62132019-08-22 03:58:50 +0000222func (f *OpenOltFlowMgr) divideAndAddFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32,
223 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
224 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) {
225 var allocID []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530226 var gemPorts []uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400227 var gemPort uint32
228 var TpInst *tp.TechProfile
manikkaraj kbf256be2019-03-25 00:13:48 +0530229
Manikkaraj kb1d51442019-07-23 10:41:02 -0400230 log.Infow("Dividing flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "portNo": portNo,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000231 "classifier": classifierInfo, "action": actionInfo, "UsMeterID": UsMeterID, "DsMeterID": DsMeterID, "TpID": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400232 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
233 // is because the flow is an NNI flow and there would be no onu resources associated with it
234 // TODO: properly deal with NNI flows
Manikkaraj kb1d51442019-07-23 10:41:02 -0400235 if onuID <= 0 {
Matt Jeanneret77199612019-07-26 18:08:35 -0400236 log.Errorw("No onu id for flow", log.Fields{"portNo": portNo, "classifer": classifierInfo, "action": actionInfo})
manikkaraj kbf256be2019-03-25 00:13:48 +0530237 return
238 }
239
Manikkaraj kb1d51442019-07-23 10:41:02 -0400240 uni := getUniPortPath(intfID, onuID, uniID)
241 log.Debugw("Uni port name", log.Fields{"uni": uni})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000242 allocID, gemPorts, TpInst = f.createTcontGemports(intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
243 if allocID == nil || gemPorts == nil || TpInst == nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400244 log.Error("alloc-id-gem-ports-tp-unavailable")
245 return
246 }
247
248 /* Flows can be added specific to gemport if p-bits are received.
249 * If no pbit mentioned then adding flows for all gemports
manikkaraj kbf256be2019-03-25 00:13:48 +0530250 */
Manikkaraj kb1d51442019-07-23 10:41:02 -0400251
252 args := make(map[string]uint32)
253 args["intfId"] = intfID
254 args["onuId"] = onuID
255 args["uniId"] = uniID
256 args["portNo"] = portNo
salmansiddiqui7ac62132019-08-22 03:58:50 +0000257 args["allocId"] = allocID[0]
Manikkaraj kb1d51442019-07-23 10:41:02 -0400258
salmansiddiqui7ac62132019-08-22 03:58:50 +0000259 f.checkAndAddFlow(args, classifierInfo, actionInfo, flow, gemPort, intfID, onuID, uniID, portNo, TpInst, allocID, gemPorts, TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530260}
261
salmansiddiqui7ac62132019-08-22 03:58:50 +0000262// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
263func (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 -0400264
salmansiddiqui7ac62132019-08-22 03:58:50 +0000265 log.Debugw("CreateSchedulerQueues", log.Fields{"Dir": Dir, "IntfID": IntfID, "OnuID": OnuID,
266 "UniID": UniID, "MeterID": MeterID, "TpInst": *TpInst, "flowMetadata": flowMetadata})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400267
salmansiddiqui7ac62132019-08-22 03:58:50 +0000268 Direction, err := verifyMeterIDAndGetDirection(MeterID, Dir)
269 if err != nil {
270 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400271 }
272
273 /* Lets make a simple assumption that if the meter-id is present on the KV store,
274 * then the scheduler and queues configuration is applied on the OLT device
275 * in the given direction.
276 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000277
Manikkaraj kb1d51442019-07-23 10:41:02 -0400278 var SchedCfg *tp_pb.SchedulerConfig
salmansiddiqui7ac62132019-08-22 03:58:50 +0000279 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(Direction, IntfID, OnuID, UniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400280 if err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000281 log.Error("Failed to get meter for intf %d, onuid %d, uniid %d", IntfID, OnuID, UniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400282 return err
283 }
284 if KvStoreMeter != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000285 if KvStoreMeter.MeterId == MeterID {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400286 log.Debug("Scheduler already created for upstream")
287 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400288 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000289 log.Errorw("Dynamic meter update not supported", log.Fields{"KvStoreMeterId": KvStoreMeter.MeterId, "MeterID-in-flow": MeterID})
290 return errors.New("invalid-meter-id-in-flow")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400291 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000292 log.Debugw("Meter-does-not-exist-Creating-new", log.Fields{"MeterID": MeterID, "Direction": Direction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400293 if Dir == tp_pb.Direction_UPSTREAM {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000294 SchedCfg = f.techprofile[IntfID].GetUsScheduler(TpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400295 } else if Dir == tp_pb.Direction_DOWNSTREAM {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000296 SchedCfg = f.techprofile[IntfID].GetDsScheduler(TpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400297 }
298 var meterConfig *ofp.OfpMeterConfig
299 if flowMetadata != nil {
300 for _, meter := range flowMetadata.Meters {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000301 if MeterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400302 meterConfig = meter
303 log.Debugw("Found-meter-config-from-flowmetadata", log.Fields{"meterConfig": meterConfig})
304 break
305 }
306 }
307 } else {
308 log.Error("Flow-metadata-is-not-present-in-flow")
309 }
310 if meterConfig == nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000311 log.Errorw("Could-not-get-meterbands-from-flowMetadata", log.Fields{"flowMetadata": flowMetadata, "MeterID": MeterID})
312 return errors.New("failed-to-get-meter-from-flowMetadata")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400313 } else if len(meterConfig.Bands) < MaxMeterBand {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000314 log.Errorw("Invalid-number-of-bands-in-meter", log.Fields{"Bands": meterConfig.Bands, "MeterID": MeterID})
315 return errors.New("invalid-number-of-bands-in-meter")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400316 }
317 cir := meterConfig.Bands[0].Rate
318 cbs := meterConfig.Bands[0].BurstSize
319 eir := meterConfig.Bands[1].Rate
320 ebs := meterConfig.Bands[1].BurstSize
321 pir := cir + eir
322 pbs := cbs + ebs
323 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
324
salmansiddiqui7ac62132019-08-22 03:58:50 +0000325 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[IntfID].GetTrafficScheduler(TpInst, SchedCfg, TrafficShaping)}
Manikkaraj kb1d51442019-07-23 10:41:02 -0400326
327 log.Debugw("Sending Traffic scheduler create to device", log.Fields{"Direction": Direction, "TrafficScheds": TrafficSched})
328 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
salmansiddiqui7ac62132019-08-22 03:58:50 +0000329 IntfId: IntfID, OnuId: OnuID,
330 UniId: UniID, PortNo: UniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400331 TrafficScheds: TrafficSched}); err != nil {
332 log.Errorw("Failed to create traffic schedulers", log.Fields{"error": err})
333 return err
334 }
335 // On receiving the CreateTrafficQueues request, the driver should create corresponding
336 // downstream queues.
salmansiddiqui7ac62132019-08-22 03:58:50 +0000337 trafficQueues := f.techprofile[IntfID].GetTrafficQueues(TpInst, Dir)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400338 log.Debugw("Sending Traffic Queues create to device", log.Fields{"Direction": Direction, "TrafficQueues": trafficQueues})
339 if _, err := f.deviceHandler.Client.CreateTrafficQueues(context.Background(),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000340 &tp_pb.TrafficQueues{IntfId: IntfID, OnuId: OnuID,
341 UniId: UniID, PortNo: UniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400342 TrafficQueues: trafficQueues}); err != nil {
343 log.Errorw("Failed to create traffic queues in device", log.Fields{"error": err})
344 return err
345 }
346
salmansiddiqui7ac62132019-08-22 03:58:50 +0000347 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400348 * store the meter id on the KV store, for further reference.
349 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000350 if err := f.resourceMgr.UpdateMeterIDForOnu(Direction, IntfID, OnuID, UniID, meterConfig); err != nil {
351 log.Error("Failed to update meter id for onu %d, meterid %d", OnuID, MeterID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400352 return err
353 }
354 log.Debugw("updated-meter-info into KV store successfully", log.Fields{"Direction": Direction,
355 "Meter": meterConfig})
356 return nil
357}
358
salmansiddiqui7ac62132019-08-22 03:58:50 +0000359// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
360func (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 -0400361
362 var Direction string
363 var SchedCfg *tp_pb.SchedulerConfig
364 var err error
salmansiddiqui7ac62132019-08-22 03:58:50 +0000365 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 -0400366 if Dir == tp_pb.Direction_UPSTREAM {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000367 SchedCfg = f.techprofile[IntfID].GetUsScheduler(TpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400368 Direction = "upstream"
369 } else if Dir == tp_pb.Direction_DOWNSTREAM {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000370 SchedCfg = f.techprofile[IntfID].GetDsScheduler(TpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400371 Direction = "downstream"
372 }
373
salmansiddiqui7ac62132019-08-22 03:58:50 +0000374 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(Direction, IntfID, OnuID, UniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400375 if err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000376 log.Errorf("Failed to get Meter for Onu %d", OnuID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400377 return err
378 }
379 if KVStoreMeter == nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000380 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 -0400381 return nil
382 }
383 cir := KVStoreMeter.Bands[0].Rate
384 cbs := KVStoreMeter.Bands[0].BurstSize
385 eir := KVStoreMeter.Bands[1].Rate
386 ebs := KVStoreMeter.Bands[1].BurstSize
387 pir := cir + eir
388 pbs := cbs + ebs
389
390 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
391
salmansiddiqui7ac62132019-08-22 03:58:50 +0000392 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[IntfID].GetTrafficScheduler(TpInst, SchedCfg, TrafficShaping)}
393 TrafficQueues := f.techprofile[IntfID].GetTrafficQueues(TpInst, Dir)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400394
395 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(context.Background(),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000396 &tp_pb.TrafficQueues{IntfId: IntfID, OnuId: OnuID,
397 UniId: UniID, PortNo: UniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400398 TrafficQueues: TrafficQueues}); err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000399 log.Errorw("Failed to remove traffic queues", log.Fields{"error": err})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400400 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400401 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000402 log.Debug("Removed traffic queues successfully")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400403 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
salmansiddiqui7ac62132019-08-22 03:58:50 +0000404 IntfId: IntfID, OnuId: OnuID,
405 UniId: UniID, PortNo: UniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400406 TrafficScheds: TrafficSched}); err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000407 log.Errorw("failed to remove traffic schedulers", log.Fields{"error": err})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400408 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400409 }
410
salmansiddiqui7ac62132019-08-22 03:58:50 +0000411 log.Debug("Removed traffic schedulers successfully")
412
413 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400414 * delete the meter id on the KV store.
415 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000416 err = f.resourceMgr.RemoveMeterIDForOnu(Direction, IntfID, OnuID, UniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400417 if err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000418 log.Errorf("Failed to remove meter for onu %d, meter id %d", OnuID, KVStoreMeter.MeterId)
419 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400420 }
421 log.Debugw("Removed-meter-from-KV-store successfully", log.Fields{"MeterId": KVStoreMeter.MeterId, "dir": Direction})
422 return err
423}
424
manikkaraj kbf256be2019-03-25 00:13:48 +0530425// This function allocates tconts and GEM ports for an ONU, currently one TCONT is supported per ONU
Manikkaraj kb1d51442019-07-23 10:41:02 -0400426func (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 +0530427 var allocID []uint32
428 var gemPortIDs []uint32
429 //If we already have allocated earlier for this onu, render them
salmansiddiqui7ac62132019-08-22 03:58:50 +0000430 if tcontID := f.resourceMgr.GetCurrentAllocIDForOnu(intfID, onuID, uniID); tcontID != 0 {
431 allocID = append(allocID, tcontID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530432 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700433 gemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400434
435 tpPath := f.getTPpath(intfID, uni, TpID)
436 // Check tech profile instance already exists for derived port name
salmansiddiqui7ac62132019-08-22 03:58:50 +0000437 techProfileInstance, err := f.techprofile[intfID].GetTPInstanceFromKVStore(TpID, tpPath)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400438 if err != nil { // This should not happen, something wrong in KV backend transaction
439 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": TpID, "path": tpPath})
440 return nil, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530441 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400442
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700443 log.Debug("Creating New TConts and Gem ports", log.Fields{"pon": intfID, "onu": onuID, "uni": uniID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530444
salmansiddiqui7ac62132019-08-22 03:58:50 +0000445 if techProfileInstance == nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530446 log.Info("Creating tech profile instance", log.Fields{"path": tpPath})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000447 techProfileInstance = f.techprofile[intfID].CreateTechProfInstance(TpID, uni, intfID)
448 if techProfileInstance == nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530449 log.Error("Tech-profile-instance-creation-failed")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400450 return nil, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530451 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000452 f.resourceMgr.UpdateTechProfileIDForOnu(intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530453 } else {
454 log.Debugw("Tech-profile-instance-already-exist-for-given port-name", log.Fields{"uni": uni})
455 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400456 if UsMeterID != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000457 if err := f.CreateSchedulerQueues(tp_pb.Direction_UPSTREAM, intfID, onuID, uniID, uniPort, techProfileInstance, UsMeterID, flowMetadata); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400458 log.Errorw("CreateSchedulerQueues Failed-upstream", log.Fields{"error": err, "meterID": UsMeterID})
459 return nil, nil, nil
460 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530461 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400462 if DsMeterID != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000463 if err := f.CreateSchedulerQueues(tp_pb.Direction_DOWNSTREAM, intfID, onuID, uniID, uniPort, techProfileInstance, DsMeterID, flowMetadata); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400464 log.Errorw("CreateSchedulerQueues Failed-downstream", log.Fields{"error": err, "meterID": DsMeterID})
465 return nil, nil, nil
466 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530467 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400468 if len(allocID) == 0 { // Created TCONT first time
salmansiddiqui7ac62132019-08-22 03:58:50 +0000469 allocID = append(allocID, techProfileInstance.UsScheduler.AllocID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400470 }
471 if len(gemPortIDs) == 0 { // Create GEM ports first time
salmansiddiqui7ac62132019-08-22 03:58:50 +0000472 for _, gem := range techProfileInstance.UpstreamGemPortAttributeList {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400473 gemPortIDs = append(gemPortIDs, gem.GemportID)
474 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530475 }
476 log.Debugw("Allocated Tcont and GEM ports", log.Fields{"allocID": allocID, "gemports": gemPortIDs})
477 // Send Tconts and GEM ports to KV store
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700478 f.storeTcontsGEMPortsIntoKVStore(intfID, onuID, uniID, allocID, gemPortIDs)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000479 return allocID, gemPortIDs, techProfileInstance
manikkaraj kbf256be2019-03-25 00:13:48 +0530480}
481
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700482func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530483
484 log.Debugw("Storing allocated Tconts and GEM ports into KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700485 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "allocID": allocID, "gemPortIDs": gemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530486 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700487 if err := f.resourceMgr.UpdateAllocIdsForOnu(intfID, onuID, uniID, allocID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530488 log.Error("Errow while uploading allocID to KV store")
489 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700490 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(intfID, onuID, uniID, gemPortIDs); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530491 log.Error("Errow while uploading GEMports to KV store")
492 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700493 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(gemPortIDs, intfID, onuID, uniID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530494 log.Error("Errow while uploading gemtopon map to KV store")
495 }
496 log.Debug("Stored tconts and GEM into KV store successfully")
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400497 for _, gemPort := range gemPortIDs {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700498 f.addGemPortToOnuInfoMap(intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400499 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530500}
501
502func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000503 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530504 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000505 for _, intfID := range techRange.IntfIds {
506 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400507 tpCount++
salmansiddiqui7ac62132019-08-22 03:58:50 +0000508 log.Debugw("Init tech profile done", log.Fields{"intfID": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530509 }
510 }
511 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400512 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530513 log.Errorw("Error while populating techprofile",
Manikkaraj kb1d51442019-07-23 10:41:02 -0400514 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000515 return errors.New("error while populating techprofile mgrs")
manikkaraj kbf256be2019-03-25 00:13:48 +0530516 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400517 log.Infow("Populated techprofile for ponports successfully",
518 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
manikkaraj kbf256be2019-03-25 00:13:48 +0530519 return nil
520}
521
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700522func (f *OpenOltFlowMgr) addUpstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530523 portNo uint32, uplinkClassifier map[string]interface{},
524 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700525 allocID uint32, gemportID uint32) {
526 uplinkClassifier[PacketTagType] = SingleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530527 log.Debugw("Adding upstream data flow", log.Fields{"uplinkClassifier": uplinkClassifier, "uplinkAction": uplinkAction})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700528 f.addHSIAFlow(intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700529 Upstream, logicalFlow, allocID, gemportID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530530 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530531}
532
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700533func (f *OpenOltFlowMgr) addDownstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530534 portNo uint32, downlinkClassifier map[string]interface{},
535 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700536 allocID uint32, gemportID uint32) {
537 downlinkClassifier[PacketTagType] = DoubleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530538 log.Debugw("Adding downstream data flow", log.Fields{"downlinkClassifier": downlinkClassifier,
539 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400540 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
541 if vlan, exists := downlinkClassifier[VlanVid]; exists {
542 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700543 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Manikkaraj kb1d51442019-07-23 10:41:02 -0400544 if uint32(metadata.(uint64)) == MkUniPortNum(intfID, onuID, uniID) {
545 log.Infow("Ignoring DL trap device flow from core", log.Fields{"flow": logicalFlow})
546 return
547 }
548 }
549 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530550 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400551
Manikkaraj k884c1242019-04-11 16:26:42 +0530552 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700553 downlinkAction[PopVlan] = true
554 downlinkAction[VlanVid] = downlinkClassifier[VlanVid]
555 f.addHSIAFlow(intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700556 Downstream, logicalFlow, allocID, gemportID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530557}
558
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700559func (f *OpenOltFlowMgr) addHSIAFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +0530560 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700561 allocID uint32, gemPortID uint32) {
Manikkaraj k884c1242019-04-11 16:26:42 +0530562 /* One of the OLT platform (Broadcom BAL) requires that symmetric
563 flows require the same flow_id to be used across UL and DL.
564 Since HSIA flow is the only symmetric flow currently, we need to
565 re-use the flow_id across both direction. The 'flow_category'
566 takes priority over flow_cookie to find any available HSIA_FLOW
567 id for the ONU.
568 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700569 log.Debugw("Adding HSIA flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "classifier": classifier,
570 "action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530571 "logicalFlow": *logicalFlow})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000572 var vlanPit uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400573 if _, ok := classifier[VlanPcp]; ok {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000574 vlanPit = classifier[VlanPcp].(uint32)
575 log.Debugw("Found pbit in the flow", log.Fields{"vlan_pit": vlanPit})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400576 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700577 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000578 flowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, HsiaFlow, vlanPit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530579 if err != nil {
580 log.Errorw("Flow id unavailable for HSIA flow", log.Fields{"direction": direction})
581 return
582 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700583 var classifierProto *openoltpb2.Classifier
584 var actionProto *openoltpb2.Action
Manikkaraj k884c1242019-04-11 16:26:42 +0530585 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
586 log.Error("Error in making classifier protobuf for hsia flow")
587 return
588 }
589 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
590 if actionProto = makeOpenOltActionField(action); actionProto == nil {
591 log.Errorw("Error in making action protobuf for hsia flow", log.Fields{"direction": direction})
592 return
593 }
594 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700595 networkIntfID := f.deviceHandler.nniIntfID
596 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
597 OnuId: int32(onuID),
598 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000599 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530600 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700601 AllocId: int32(allocID),
602 NetworkIntfId: int32(networkIntfID),
603 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530604 Classifier: classifierProto,
605 Action: actionProto,
606 Priority: int32(logicalFlow.Priority),
607 Cookie: logicalFlow.Cookie,
608 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400609 if ok := f.addFlowToDevice(logicalFlow, &flow); ok {
Manikkaraj k884c1242019-04-11 16:26:42 +0530610 log.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000611 flowsToKVStore := f.getUpdatedFlowInfo(&flow, flowStoreCookie, HsiaFlow, flowID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530612 if err := f.updateFlowInfoToKVStore(flow.AccessIntfId,
613 flow.OnuId,
614 flow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400615 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530616 log.Errorw("Error uploading HSIA flow into KV store", log.Fields{"flow": flow, "direction": direction, "error": err})
617 return
618 }
619 }
620}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700621func (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 +0530622
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700623 var dhcpFlow openoltpb2.Flow
624 var actionProto *openoltpb2.Action
625 var classifierProto *openoltpb2.Classifier
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530626
627 // Clear the action map
628 for k := range action {
629 delete(action, k)
630 }
631
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700632 action[TrapToHost] = true
633 classifier[UDPSrc] = uint32(68)
634 classifier[UDPDst] = uint32(67)
635 classifier[PacketTagType] = SingleTag
636 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530637
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700638 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530639
Manikkaraj kb1d51442019-07-23 10:41:02 -0400640 flowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, "", 0 /*classifier[VLAN_PCP].(uint32)*/)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530641
642 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700643 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530644 return
645 }
646
647 log.Debugw("Creating UL DHCP flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID})
648
649 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
650 log.Error("Error in making classifier protobuf for ul flow")
651 return
652 }
653 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
654 if actionProto = makeOpenOltActionField(action); actionProto == nil {
655 log.Error("Error in making action protobuf for ul flow")
656 return
657 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700658 networkIntfID := f.deviceHandler.nniIntfID
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530659
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700660 dhcpFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
661 OnuId: int32(onuID),
662 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530663 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700664 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700665 AllocId: int32(allocID),
666 NetworkIntfId: int32(networkIntfID),
667 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530668 Classifier: classifierProto,
669 Action: actionProto,
670 Priority: int32(logicalFlow.Priority),
671 Cookie: logicalFlow.Cookie,
672 PortNo: portNo}
673
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400674 if ok := f.addFlowToDevice(logicalFlow, &dhcpFlow); ok {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530675 log.Debug("DHCP UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400676 flowsToKVStore := f.getUpdatedFlowInfo(&dhcpFlow, flowStoreCookie, "DHCP", flowID)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530677 if err := f.updateFlowInfoToKVStore(dhcpFlow.AccessIntfId,
678 dhcpFlow.OnuId,
679 dhcpFlow.UniId,
680 dhcpFlow.FlowId, flowsToKVStore); err != nil {
681 log.Errorw("Error uploading DHCP UL flow into KV store", log.Fields{"flow": dhcpFlow, "error": err})
682 return
683 }
684 }
685
manikkaraj kbf256be2019-03-25 00:13:48 +0530686 return
687}
688
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700689// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
690func (f *OpenOltFlowMgr) addEAPOLFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, vlanID uint32) {
691 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 +0530692
693 uplinkClassifier := make(map[string]interface{})
694 uplinkAction := make(map[string]interface{})
695 downlinkClassifier := make(map[string]interface{})
696 downlinkAction := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700697 var upstreamFlow openoltpb2.Flow
698 var downstreamFlow openoltpb2.Flow
manikkaraj kbf256be2019-03-25 00:13:48 +0530699
700 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700701 uplinkClassifier[EthType] = uint32(EapEthType)
702 uplinkClassifier[PacketTagType] = SingleTag
703 uplinkClassifier[VlanVid] = vlanID
manikkaraj kbf256be2019-03-25 00:13:48 +0530704 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700705 uplinkAction[TrapToHost] = true
706 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530707 //Add Uplink EAPOL Flow
Manikkaraj kb1d51442019-07-23 10:41:02 -0400708 uplinkFlowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530709 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700710 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manikkaraj k884c1242019-04-11 16:26:42 +0530711 return
manikkaraj kbf256be2019-03-25 00:13:48 +0530712 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700713 var classifierProto *openoltpb2.Classifier
714 var actionProto *openoltpb2.Action
715 log.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530716
717 if classifierProto = makeOpenOltClassifierField(uplinkClassifier); classifierProto == nil {
718 log.Error("Error in making classifier protobuf for ul flow")
719 return
720 }
721 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
722 if actionProto = makeOpenOltActionField(uplinkAction); actionProto == nil {
723 log.Error("Error in making action protobuf for ul flow")
724 return
725 }
726 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700727 networkIntfID := f.deviceHandler.nniIntfID
728 upstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
729 OnuId: int32(onuID),
730 UniId: int32(uniID),
731 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700732 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700733 AllocId: int32(allocID),
734 NetworkIntfId: int32(networkIntfID),
735 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530736 Classifier: classifierProto,
737 Action: actionProto,
738 Priority: int32(logicalFlow.Priority),
739 Cookie: logicalFlow.Cookie,
740 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400741 if ok := f.addFlowToDevice(logicalFlow, &upstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530742 log.Debug("EAPOL UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400743 flowCategory := "EAPOL"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700744 flowsToKVStore := f.getUpdatedFlowInfo(&upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530745 if err := f.updateFlowInfoToKVStore(upstreamFlow.AccessIntfId,
746 upstreamFlow.OnuId,
747 upstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400748 upstreamFlow.FlowId,
749 /* lowCategory, */
750 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530751 log.Errorw("Error uploading EAPOL UL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
752 return
753 }
754 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400755 // Dummy Downstream flow due to BAL 2.6 limitation
756 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530757 /* Add Downstream EAPOL Flow, Only for first EAP flow (BAL
758 # requirement)
759 # On one of the platforms (Broadcom BAL), when same DL classifier
760 # vlan was used across multiple ONUs, eapol flow re-adds after
761 # flow delete (cases of onu reboot/disable) fails.
762 # In order to generate unique vlan, a combination of intf_id
763 # onu_id and uniId is used.
764 # uniId defaults to 0, so add 1 to it.
765 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700766 log.Debugw("Creating DL EAPOL flow with default vlan", log.Fields{"vlan": vlanID})
767 specialVlanDlFlow := 4090 - intfID*onuID*(uniID+1)
manikkaraj kbf256be2019-03-25 00:13:48 +0530768 // Assert that we do not generate invalid vlans under no condition
769 if specialVlanDlFlow <= 2 {
770 log.Fatalw("invalid-vlan-generated", log.Fields{"vlan": specialVlanDlFlow})
771 return
772 }
773 log.Debugw("specialVlanEAPOLDlFlow:", log.Fields{"dl_vlan": specialVlanDlFlow})
774 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700775 downlinkClassifier[PacketTagType] = SingleTag
Manikkaraj kb1d51442019-07-23 10:41:02 -0400776 downlinkClassifier[EthType] = uint32(EapEthType)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700777 downlinkClassifier[VlanVid] = uint32(specialVlanDlFlow)
manikkaraj kbf256be2019-03-25 00:13:48 +0530778 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700779 downlinkAction[PushVlan] = true
780 downlinkAction[VlanVid] = vlanID
781 flowStoreCookie := getFlowStoreCookie(downlinkClassifier, gemPortID)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000782 downlinkFlowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530783 if err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530784 log.Errorw("flowId unavailable for DL EAPOL",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700785 log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
manikkaraj kbf256be2019-03-25 00:13:48 +0530786 return
787 }
788 log.Debugw("Creating DL EAPOL flow",
salmansiddiqui7ac62132019-08-22 03:58:50 +0000789 log.Fields{"dl_classifier": downlinkClassifier, "dl_action": downlinkAction, "downlinkFlowID": downlinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530790 if classifierProto = makeOpenOltClassifierField(downlinkClassifier); classifierProto == nil {
791 log.Error("Error in making classifier protobuf for downlink flow")
792 return
793 }
794 if actionProto = makeOpenOltActionField(downlinkAction); actionProto == nil {
795 log.Error("Error in making action protobuf for dl flow")
796 return
797 }
798 // Downstream flow in grpc protobuf
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700799 downstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
800 OnuId: int32(onuID),
801 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000802 FlowId: downlinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700803 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700804 AllocId: int32(allocID),
805 NetworkIntfId: int32(networkIntfID),
806 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530807 Classifier: classifierProto,
808 Action: actionProto,
809 Priority: int32(logicalFlow.Priority),
810 Cookie: logicalFlow.Cookie,
811 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400812 if ok := f.addFlowToDevice(logicalFlow, &downstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530813 log.Debug("EAPOL DL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400814 flowCategory := ""
salmansiddiqui7ac62132019-08-22 03:58:50 +0000815 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamFlow, flowStoreCookie, flowCategory, downlinkFlowID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530816 if err := f.updateFlowInfoToKVStore(downstreamFlow.AccessIntfId,
817 downstreamFlow.OnuId,
818 downstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400819 downstreamFlow.FlowId,
820 /* flowCategory, */
821 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530822 log.Errorw("Error uploading EAPOL DL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
823 return
824 }
825 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530826 }
827 log.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
828}
829
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700830func makeOpenOltClassifierField(classifierInfo map[string]interface{}) *openoltpb2.Classifier {
831 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -0700832
833 classifier.EthType, _ = classifierInfo[EthType].(uint32)
834 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
835 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
836 vid := vlanID & VlanvIDMask
837 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -0400838 classifier.OVid = vid
839 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530840 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700841 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
842 vid := uint32(metadata)
843 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -0400844 classifier.IVid = vid
845 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530846 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700847 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400848 if vlanPcp == 0 {
849 classifier.OPbits = VlanPCPMask
850 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700851 classifier.OPbits = vlanPcp & VlanPCPMask
Manikkaraj kb1d51442019-07-23 10:41:02 -0400852 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530853 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700854 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
855 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
856 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
857 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
858 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
859 classifier.PktTagType = pktTagType
860
861 switch pktTagType {
862 case SingleTag:
863 case DoubleTag:
864 case Untagged:
865 default:
manikkaraj kbf256be2019-03-25 00:13:48 +0530866 log.Error("Invalid tag type in classifier") // should not hit
867 return nil
868 }
869 }
870 return &classifier
871}
872
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700873func makeOpenOltActionField(actionInfo map[string]interface{}) *openoltpb2.Action {
874 var actionCmd openoltpb2.ActionCmd
875 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +0530876 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700877 if _, ok := actionInfo[PopVlan]; ok {
878 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530879 action.Cmd.RemoveOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700880 } else if _, ok := actionInfo[PushVlan]; ok {
881 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530882 action.Cmd.AddOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700883 } else if _, ok := actionInfo[TrapToHost]; ok {
884 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +0530885 } else {
886 log.Errorw("Invalid-action-field", log.Fields{"action": actionInfo})
887 return nil
888 }
889 return &action
890}
891
Manikkaraj kb1d51442019-07-23 10:41:02 -0400892func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uni string, TpID uint32) string {
893 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530894}
895
Devmalya Paul495b94a2019-08-27 19:42:00 -0400896// DeleteTechProfileInstance removes the tech profile instance from persistent storage
897func (f *OpenOltFlowMgr) DeleteTechProfileInstance(intfID uint32, onuID uint32, uniID uint32, sn string) error {
898 tpID := f.resourceMgr.GetTechProfileIDForOnu(intfID, onuID, uniID)
899 uniPortName := fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
900 if err := f.techprofile[intfID].DeleteTechProfileInstance(tpID, uniPortName); err != nil {
901 log.Debugw("Failed-to-delete-tp-instance-from-kv-store", log.Fields{"tp-id": tpID, "uni-port-name": uniPortName})
902 return err
903 }
904 return nil
905}
906
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700907func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530908 if len(classifier) == 0 { // should never happen
909 log.Error("Invalid classfier object")
910 return 0
911 }
912 var jsonData []byte
913 var flowString string
914 var err error
915 // TODO: Do we need to marshall ??
916 if jsonData, err = json.Marshal(classifier); err != nil {
917 log.Error("Failed to encode classifier")
918 return 0
919 }
920 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700921 if gemPortID != 0 {
922 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +0530923 }
924 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700925 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +0530926 hash := big.NewInt(0)
927 hash.SetBytes(h.Sum(nil))
928 return hash.Uint64()
929}
930
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700931func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openoltpb2.Flow, flowStoreCookie uint64, flowCategory string, deviceFlowID uint32) *[]rsrcMgr.FlowInfo {
932 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
933 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400934 /* For flows which trap out of the NNI, the AccessIntfId is invalid
935 (set to -1). In such cases, we need to refer to the NetworkIntfId .
936 */
937 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700938 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400939 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700940 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400941 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700942 // Get existing flows matching flowid for given subscriber from KV store
943 existingFlows := f.resourceMgr.GetFlowIDInfo(intfID, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -0400944 if existingFlows != nil {
945 log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700946 //for _, f := range *existingFlows {
947 // flows = append(flows, f)
948 //}
949 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -0400950 }
951 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 +0530952 return &flows
953}
954
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400955//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
956// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
957// var intfId uint32
958// /* For flows which trap out of the NNI, the AccessIntfId is invalid
959// (set to -1). In such cases, we need to refer to the NetworkIntfId .
960// */
961// if flow.AccessIntfId != -1 {
962// intfId = uint32(flow.AccessIntfId)
963// } else {
964// intfId = uint32(flow.NetworkIntfId)
965// }
966// // Get existing flows matching flowid for given subscriber from KV store
967// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
968// if existingFlows != nil {
969// log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
970// for _, f := range *existingFlows {
971// flows = append(flows, f)
972// }
973// }
974// log.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
975// return &flows
976//}
977
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700978func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
manikkaraj k17652a72019-05-06 09:06:36 -0400979 log.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700980 if err := f.resourceMgr.UpdateFlowIDInfo(intfID, onuID, uniID, flowID, flows); err != nil {
manikkaraj k17652a72019-05-06 09:06:36 -0400981 log.Debug("Error while Storing flow into KV store")
982 return err
983 }
984 log.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +0530985 return nil
986}
987
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700988func (f *OpenOltFlowMgr) addFlowToDevice(logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) bool {
Daniele Rossi22db98e2019-07-11 11:50:00 +0000989
990 var intfID uint32
991 /* For flows which trap out of the NNI, the AccessIntfId is invalid
992 (set to -1). In such cases, we need to refer to the NetworkIntfId .
993 */
994 if deviceFlow.AccessIntfId != -1 {
995 intfID = uint32(deviceFlow.AccessIntfId)
996 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400997 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +0000998 intfID = uint32(deviceFlow.NetworkIntfId)
999 }
1000
manikkaraj kbf256be2019-03-25 00:13:48 +05301001 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1002 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001003
1004 st, _ := status.FromError(err)
1005 if st.Code() == codes.AlreadyExists {
1006 log.Debug("Flow already exixts", log.Fields{"err": err, "deviceFlow": deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301007 return false
1008 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001009
1010 if err != nil {
1011 log.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": deviceFlow})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001012 f.resourceMgr.FreeFlowID(intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001013 return false
1014 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001015 log.Debugw("Flow added to device successfully ", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001016 f.registerFlow(logicalFlow, deviceFlow)
1017 return true
1018}
1019
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001020func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) bool {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001021 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1022 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1023 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001024 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
1025 log.Warnw("Can not remove flow from device since it's unreachable", log.Fields{"err": err, "deviceFlow": deviceFlow})
1026 //Assume the flow is removed
1027 return true
1028 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001029 log.Errorw("Failed to Remove flow from device", log.Fields{"err": err, "deviceFlow": deviceFlow})
1030 return false
serkant.uluderya245caba2019-09-24 23:15:29 -07001031
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001032 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001033 log.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301034 return true
1035}
1036
1037/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1038 //update core flows_proxy : flows_proxy.update('/', flows)
1039}
1040
1041func generateStoredId(flowId uint32, direction string)uint32{
1042
David K. Bainbridge82efc492019-09-04 09:57:11 -07001043 if direction == Upstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301044 log.Debug("Upstream flow shifting flowid")
1045 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001046 }else if direction == Downstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301047 log.Debug("Downstream flow not shifting flowid")
1048 return flowId
1049 }else{
1050 log.Errorw("Unrecognized direction",log.Fields{"direction": direction})
1051 return flowId
1052 }
1053}
1054
1055*/
1056
Humera Kouser94d7a842019-08-25 19:04:32 -04001057func (f *OpenOltFlowMgr) addLLDPFlow(flow *ofp.OfpFlowStats, portNo uint32) {
1058
1059 classifierInfo := make(map[string]interface{})
1060 actionInfo := make(map[string]interface{})
1061
1062 classifierInfo[EthType] = uint32(LldpEthType)
1063 classifierInfo[PacketTagType] = Untagged
1064 actionInfo[TrapToHost] = true
1065
1066 // LLDP flow is installed to trap LLDP packets on the NNI port.
1067 // We manage flow_id resource pool on per PON port basis.
1068 // Since this situation is tricky, as a hack, we pass the NNI port
1069 // index (network_intf_id) as PON port Index for the flow_id resource
1070 // pool. Also, there is no ONU Id available for trapping LLDP packets
1071 // on NNI port, use onu_id as -1 (invalid)
1072 // ****************** CAVEAT *******************
1073 // This logic works if the NNI Port Id falls within the same valid
1074 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1075 // we need to have a re-look at this.
1076 // *********************************************
1077
1078 var onuID = -1
1079 var uniID = -1
1080 var gemPortID = -1
1081
1082 var networkInterfaceID = IntfIDFromNniPortNum(portNo)
1083 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
1084 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), flowStoreCookie); present {
1085 log.Debug("Flow-exists--not-re-adding")
1086 return
1087 }
1088 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
1089
1090 if err != nil {
1091 log.Errorw("Flow id unavailable for LLDP traponNNI flow", log.Fields{"error": err})
1092 return
1093 }
1094 var classifierProto *openoltpb2.Classifier
1095 var actionProto *openoltpb2.Action
1096 if classifierProto = makeOpenOltClassifierField(classifierInfo); classifierProto == nil {
1097 log.Error("Error in making classifier protobuf for LLDP trap on nni flow")
1098 return
1099 }
1100 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1101 if actionProto = makeOpenOltActionField(actionInfo); actionProto == nil {
1102 log.Error("Error in making action protobuf for LLDP trap on nni flow")
1103 return
1104 }
1105 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
1106
1107 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1108 OnuId: int32(onuID), // OnuId not required
1109 UniId: int32(uniID), // UniId not used
1110 FlowId: flowID,
1111 FlowType: Downstream,
1112 NetworkIntfId: int32(networkInterfaceID),
1113 GemportId: int32(gemPortID),
1114 Classifier: classifierProto,
1115 Action: actionProto,
1116 Priority: int32(flow.Priority),
1117 Cookie: flow.Cookie,
1118 PortNo: portNo}
1119 if ok := f.addFlowToDevice(flow, &downstreamflow); ok {
1120 log.Debug("LLDP trap on NNI flow added to device successfully")
1121 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID)
1122 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1123 int32(onuID),
1124 int32(uniID),
1125 flowID, flowsToKVStore); err != nil {
1126 log.Errorw("Error uploading LLDP flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1127 }
1128 }
1129 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301130}
1131
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001132func getUniPortPath(intfID uint32, onuID uint32, uniID uint32) string {
1133 return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1134}
1135
1136//getOnuChildDevice to fetch onu
1137func (f *OpenOltFlowMgr) getOnuChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
1138 log.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
1139 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
1140 onuDevice := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301141 if onuDevice == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001142 log.Errorw("onu not found", log.Fields{"intfId": parentPortNo, "onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301143 return nil, errors.New("onu not found")
manikkaraj kbf256be2019-03-25 00:13:48 +05301144 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301145 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1146 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301147}
1148
1149func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001150 log.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301151 return nil
1152}
1153
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001154func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
1155 log.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301156}
1157
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001158func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001159 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001160 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001161 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001162 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001163}
1164
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001165func (f *OpenOltFlowMgr) clearFlowFromResourceManager(flow *ofp.OfpFlowStats, flowID uint32, flowDirection string) {
1166 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowID": flowID, "flowDirection": flowDirection, "flow": *flow})
Humera Kouser94d7a842019-08-25 19:04:32 -04001167 portNum, ponIntf, onuID, uniID, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001168 if err != nil {
1169 log.Error(err)
1170 return
1171 }
1172 log.Debugw("Extracted access info from flow to be deleted",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001173 log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001174
Humera Kouser94d7a842019-08-25 19:04:32 -04001175 if ethType == LldpEthType {
1176 var networkInterfaceID uint32
1177 var onuID = -1
1178 var uniID = -1
1179
1180 networkInterfaceID = IntfIDFromNniPortNum(inPort)
1181 f.resourceMgr.FreeFlowID(networkInterfaceID, int32(onuID), int32(uniID), flowID)
1182 return
1183 }
1184
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001185 flowsInfo := f.resourceMgr.GetFlowIDInfo(ponIntf, onuID, uniID, flowID)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001186 if flowsInfo == nil {
1187 log.Debugw("No FlowInfo found found in KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001188 log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001189 return
1190 }
1191 var updatedFlows []rsrcMgr.FlowInfo
1192
1193 for _, flow := range *flowsInfo {
1194 updatedFlows = append(updatedFlows, flow)
1195 }
1196
1197 for i, storedFlow := range updatedFlows {
1198 if flowDirection == storedFlow.Flow.FlowType {
1199 //Remove the Flow from FlowInfo
1200 log.Debugw("Removing flow to be deleted", log.Fields{"flow": storedFlow})
1201 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1202 break
1203 }
1204 }
1205
1206 if len(updatedFlows) >= 0 {
1207 // There are still flows referencing the same flow_id.
1208 // So the flow should not be freed yet.
1209 // For ex: Case of HSIA where same flow is shared
1210 // between DS and US.
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001211 f.updateFlowInfoToKVStore(int32(ponIntf), int32(onuID), int32(uniID), flowID, &updatedFlows)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001212 if len(updatedFlows) == 0 {
1213 log.Debugw("Releasing flow Id to resource manager", log.Fields{"ponIntf": ponIntf, "onuId": onuID, "uniId": uniID, "flowId": flowID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001214 f.resourceMgr.FreeFlowID(ponIntf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001215 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001216 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001217 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ponIntf, onuID, uniID)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001218 if len(flowIds) == 0 {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001219 log.Debugf("Flow count for subscriber %d is zero", onuID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001220 kvstoreTpID := f.resourceMgr.GetTechProfileIDForOnu(ponIntf, onuID, uniID)
1221 if kvstoreTpID == 0 {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001222 log.Warnw("Could-not-find-techprofile-tableid-for-uni", log.Fields{"ponIntf": ponIntf, "onuId": onuID, "uniId": uniID})
1223 return
1224 }
1225 uni := getUniPortPath(ponIntf, onuID, uniID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001226 tpPath := f.getTPpath(ponIntf, uni, kvstoreTpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001227 log.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001228 techprofileInst, err := f.techprofile[ponIntf].GetTPInstanceFromKVStore(kvstoreTpID, tpPath)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001229 if err != nil { // This should not happen, something wrong in KV backend transaction
1230 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": 20, "path": tpPath})
1231 return
1232 }
1233 if techprofileInst == nil {
1234 log.Errorw("Tech-profile-instance-does-not-exist-in-KV Store", log.Fields{"tpPath": tpPath})
1235 return
1236 }
1237
1238 f.RemoveSchedulerQueues(tp_pb.Direction_UPSTREAM, ponIntf, onuID, uniID, portNum, techprofileInst)
1239 f.RemoveSchedulerQueues(tp_pb.Direction_DOWNSTREAM, ponIntf, onuID, uniID, portNum, techprofileInst)
1240 } else {
1241 log.Debugf("Flow ids for subscriber", log.Fields{"onu": onuID, "flows": flowIds})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001242 }
1243}
1244
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001245//RemoveFlow removes the flow from the device
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001246func (f *OpenOltFlowMgr) RemoveFlow(flow *ofp.OfpFlowStats) {
1247 log.Debugw("Removing Flow", log.Fields{"flow": flow})
1248 var deviceFlowsToRemove []ofp.OfpFlowStats
1249 var deletedFlowsIdx []int
1250 for _, curFlow := range f.storedDeviceFlows {
1251 if curFlow.Cookie == flow.Id {
1252 log.Debugw("Found found matching flow-cookie", log.Fields{"curFlow": curFlow})
1253 deviceFlowsToRemove = append(deviceFlowsToRemove, curFlow)
1254 }
1255 }
1256 log.Debugw("Flows to be deleted", log.Fields{"deviceFlowsToRemove": deviceFlowsToRemove})
1257 for index, curFlow := range deviceFlowsToRemove {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001258 id, direction := f.decodeStoredID(curFlow.GetId())
1259 removeFlowMessage := openoltpb2.Flow{FlowId: uint32(id), FlowType: direction}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001260 if ok := f.removeFlowFromDevice(&removeFlowMessage); ok {
1261 log.Debug("Flow removed from device successfully")
1262 deletedFlowsIdx = append(deletedFlowsIdx, index)
1263 f.clearFlowFromResourceManager(flow, uint32(id), direction) //TODO: Take care of the limitations
1264 }
1265
1266 }
1267 // Can be done in separate go routine as it takes time ?
1268 for _, flowToRemove := range deletedFlowsIdx {
1269 for index, storedFlow := range f.storedDeviceFlows {
1270 if deviceFlowsToRemove[flowToRemove].Cookie == storedFlow.Cookie {
1271 log.Debugw("Removing flow from local Store", log.Fields{"flow": storedFlow})
1272 f.storedDeviceFlows = append(f.storedDeviceFlows[:index], f.storedDeviceFlows[index+1:]...)
1273 break
1274 }
1275 }
1276 }
1277 log.Debugw("Flows removed from the data store",
1278 log.Fields{"number_of_flows_removed": len(deviceFlowsToRemove), "updated_stored_flows": f.storedDeviceFlows})
1279 return
1280}
1281
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001282// AddFlow add flow to device
Manikkaraj kb1d51442019-07-23 10:41:02 -04001283func (f *OpenOltFlowMgr) AddFlow(flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001284 classifierInfo := make(map[string]interface{})
1285 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001286 var UsMeterID uint32
1287 var DsMeterID uint32
1288
1289 log.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001290 formulateClassifierInfoFromFlow(classifierInfo, flow)
1291
1292 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
1293 if err != nil {
1294 // Error logging is already done in the called function
1295 // So just return in case of error
1296 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301297 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001298
manikkaraj k17652a72019-05-06 09:06:36 -04001299 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00001300 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
1301 if err != nil {
1302 // error if any, already logged in the called function
1303 return
manikkaraj k17652a72019-05-06 09:06:36 -04001304 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001305
David K. Bainbridge82efc492019-09-04 09:57:11 -07001306 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[Output]})
1307 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00001308
Humera Kouser94d7a842019-08-25 19:04:32 -04001309 if ethType, ok := classifierInfo[EthType]; ok {
1310 if ethType.(uint32) == LldpEthType {
1311 log.Info("Adding LLDP flow")
1312 f.addLLDPFlow(flow, portNo)
1313 return
1314 }
1315 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001316 if ipProto, ok := classifierInfo[IPProto]; ok {
1317 if ipProto.(uint32) == IPProtoDhcp {
1318 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001319 if udpSrc.(uint32) == uint32(67) {
1320 log.Debug("trap-dhcp-from-nni-flow")
1321 f.addDHCPTrapFlowOnNNI(flow, classifierInfo, portNo)
1322 return
1323 }
1324 }
1325 }
1326 }
A R Karthick1f85b802019-10-11 05:06:05 +00001327
1328 f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
1329
Manikkaraj kb1d51442019-07-23 10:41:02 -04001330 /* Metadata 8 bytes:
1331 Most Significant 2 Bytes = Inner VLAN
1332 Next 2 Bytes = Tech Profile ID(TPID)
1333 Least Significant 4 Bytes = Port ID
David K. Bainbridge82efc492019-09-04 09:57:11 -07001334 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
Manikkaraj kb1d51442019-07-23 10:41:02 -04001335 subscriber related flows.
1336 */
Scott Baker355d1742019-10-24 10:57:52 -07001337 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001338 if metadata == 0 {
1339 log.Error("Metadata is not present in flow which is mandatory")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001340 return
1341 }
Scott Baker355d1742019-10-24 10:57:52 -07001342 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001343 kvstoreTpID := f.resourceMgr.GetTechProfileIDForOnu(intfID, onuID, uniID)
1344 if kvstoreTpID == 0 {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001345 log.Debugf("tpid-not-present-in-kvstore, using tp id %d from flow metadata", TpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001346 } else if kvstoreTpID != uint32(TpID) {
1347 log.Error(" Tech-profile-updates-not-supported", log.Fields{"Tpid-in-flow": TpID, "kvstore-TpId": kvstoreTpID})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001348 return
1349 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001350 log.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001351 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07001352 UsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001353 log.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
1354 } else {
Scott Baker355d1742019-10-24 10:57:52 -07001355 DsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001356 log.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
1357
1358 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001359 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001360}
1361
1362//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04001363func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001364
1365 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301366 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001367 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301368 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301369 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301370 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04001371
Manikkaraj kb1d51442019-07-23 10:41:02 -04001372 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001373 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
manikkaraj k17652a72019-05-06 09:06:36 -04001374 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
1375 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1376 tpDownloadMsg,
1377 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
1378 f.deviceHandler.deviceType,
1379 onuDevice.Type,
1380 onuDevice.Id,
1381 onuDevice.ProxyAddress.DeviceId, "")
1382 if sendErr != nil {
1383 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1384 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1385 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1386 return sendErr
1387 }
1388 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05301389 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301390}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001391
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001392//UpdateOnuInfo function adds onu info to cache
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001393func (f *OpenOltFlowMgr) UpdateOnuInfo(intfID uint32, onuID uint32, serialNum string) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001394 onu := onuInfo{intfID: intfID, onuID: onuID, serialNumber: serialNum}
1395 onuIDkey := onuIDKey{intfID: intfID, onuID: onuID}
William Kurkian740a09c2019-10-23 17:07:38 -04001396 f.onuIdsLock.Lock()
1397 defer f.onuIdsLock.Unlock()
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001398 f.onuIds[onuIDkey] = onu
1399 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
1400}
1401
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001402//addGemPortToOnuInfoMap function stores adds GEMport to ONU map
1403func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(intfID uint32, onuID uint32, gemPort uint32) {
1404 onuIDkey := onuIDKey{intfID: intfID, onuID: onuID}
William Kurkian740a09c2019-10-23 17:07:38 -04001405 f.onuIdsLock.RLock()
1406 defer f.onuIdsLock.RUnlock()
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001407 if val, ok := f.onuIds[onuIDkey]; ok {
kdarapu3248f9a2019-10-03 13:54:52 +05301408 onuInf := val
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001409 gemportKey := gemPortKey{intfID: intfID, gemPort: gemPort}
kdarapu3248f9a2019-10-03 13:54:52 +05301410 f.onuGemPortIds[gemportKey] = onuInf
1411 log.Debugw("Cached Gemport to Onuinfo map", log.Fields{"GemPort": gemPort, "intfId": onuInf.intfID, "onuId": onuInf.onuID})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001412 return
1413 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001414 log.Errorw("OnuInfo not found", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001415}
1416
1417// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001418
1419//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
1420func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
1421 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 -04001422 if serialNumber != "" {
kdarapu3248f9a2019-10-03 13:54:52 +05301423 if onuInf, ok := f.onuSerialNumbers[serialNumber]; ok {
1424 return onuInf.onuID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001425 }
1426 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001427 gemportKey := gemPortKey{intfID: intfID, gemPort: gemPortID}
kdarapu3248f9a2019-10-03 13:54:52 +05301428 if onuInf, ok := f.onuGemPortIds[gemportKey]; ok {
1429 log.Debugw("Retrieved onu info from access", log.Fields{"intfId": intfID, "gemPortId": gemPortID, "onuId": onuInf.onuID})
1430 return onuInf.onuID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001431 }
1432 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001433 log.Errorw("onuid is not found", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPort": gemPortID})
1434 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 -04001435}
1436
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001437//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
1438func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001439 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001440 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001441 var err error
1442
1443 if packetIn.IntfType == "pon" {
1444 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001445 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001446 log.Errorw("Unable to get ONU ID from GEM/PON port", log.Fields{"pon port": packetIn.IntfId, "gemport": packetIn.GemportId})
1447 return logicalPortNum, err
1448 }
1449 if packetIn.PortNo != 0 {
1450 logicalPortNum = packetIn.PortNo
1451 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001452 uniID := uint32(0) // FIXME - multi-uni support
1453 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001454 }
1455 // 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 -07001456 pktInkey := packetInInfoKey{intfID: packetIn.IntfId, onuID: onuID, logicalPort: logicalPortNum}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001457 f.packetInGemPort[pktInkey] = packetIn.GemportId
1458 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001459 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001460 }
1461 log.Debugw("Retrieved logicalport from packet-in", log.Fields{"logicalPortNum": logicalPortNum, "IntfType": packetIn.IntfType})
1462 return logicalPortNum, nil
1463}
1464
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001465//GetPacketOutGemPortID returns gemPortId
1466func (f *OpenOltFlowMgr) GetPacketOutGemPortID(intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
1467 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001468 var err error
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001469 key := packetInInfoKey{intfID: intfID, onuID: onuID, logicalPort: portNum}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001470 if val, ok := f.packetInGemPort[key]; ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001471 gemPortID = val
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001472 } else {
1473 log.Errorw("Key-Error while fetching packet-out GEM port", log.Fields{"key": key})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001474 err = errors.New("key-error while fetching packet-out GEM port")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001475 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001476 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001477}
1478
Manikkaraj kb1d51442019-07-23 10:41:02 -04001479func installFlowOnAllGemports(
1480 f1 func(intfId uint32, onuId uint32, uniId uint32,
1481 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
1482 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32),
1483 f2 func(intfId uint32, onuId uint32, uniId uint32, portNo uint32,
1484 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32),
1485 args map[string]uint32,
1486 classifier map[string]interface{}, action map[string]interface{},
1487 logicalFlow *ofp.OfpFlowStats,
1488 gemPorts []uint32,
1489 FlowType string,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001490 vlanID ...uint32) {
1491 log.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
1492 for _, gemPortID := range gemPorts {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001493 if FlowType == HsiaFlow || FlowType == DhcpFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001494 f1(args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001495 } else if FlowType == EapolFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001496 f2(args["intfId"], args["onuId"], args["uniId"], args["portNo"], logicalFlow, args["allocId"], gemPortID, vlanID[0])
Manikkaraj kb1d51442019-07-23 10:41:02 -04001497 } else {
1498 log.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
1499 return
1500 }
1501 }
1502}
1503
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001504func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
1505 log.Debug("Adding trap-dhcp-of-nni-flow")
1506 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001507 classifier[PacketTagType] = DoubleTag
1508 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001509 /* We manage flowId resource pool on per PON port basis.
1510 Since this situation is tricky, as a hack, we pass the NNI port
1511 index (network_intf_id) as PON port Index for the flowId resource
1512 pool. Also, there is no ONU Id available for trapping DHCP packets
1513 on NNI port, use onu_id as -1 (invalid)
1514 ****************** CAVEAT *******************
1515 This logic works if the NNI Port Id falls within the same valid
1516 range of PON Port Ids. If this doesn't work for some OLT Vendor
1517 we need to have a re-look at this.
1518 *********************************************
1519 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001520 onuID := -1
1521 uniID := -1
1522 gemPortID := -1
1523 allocID := -1
1524 networkInterfaceID := f.deviceHandler.nniIntfID
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001525 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001526 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), flowStoreCookie); present {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001527 log.Debug("Flow-exists--not-re-adding")
1528 return
1529 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001530 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001531 if err != nil {
1532 log.Errorw("Flow id unavailable for DHCP traponNNI flow", log.Fields{"error": err})
1533 return
1534 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001535 var classifierProto *openoltpb2.Classifier
1536 var actionProto *openoltpb2.Action
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001537 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
1538 log.Error("Error in making classifier protobuf for dhcp trap on nni flow")
1539 return
1540 }
1541 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1542 if actionProto = makeOpenOltActionField(action); actionProto == nil {
1543 log.Error("Error in making action protobuf for dhcp trap on nni flow")
1544 return
1545 }
1546 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001547 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1548 OnuId: int32(onuID), // OnuId not required
1549 UniId: int32(uniID), // UniId not used
1550 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001551 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001552 AllocId: int32(allocID), // AllocId not used
1553 NetworkIntfId: int32(networkInterfaceID),
1554 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001555 Classifier: classifierProto,
1556 Action: actionProto,
1557 Priority: int32(logicalFlow.Priority),
1558 Cookie: logicalFlow.Cookie,
1559 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001560 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001561 log.Debug("DHCP trap on NNI flow added to device successfully")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001562 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID)
1563 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1564 int32(onuID),
1565 int32(uniID),
1566 flowID, flowsToKVStore); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001567 log.Errorw("Error uploading DHCP DL flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1568 }
1569 }
1570 return
1571}
salmansiddiqui7ac62132019-08-22 03:58:50 +00001572
1573func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
1574 if MeterID == 0 { // This should never happen
1575 log.Error("Invalid meter id")
1576 return "", errors.New("invalid meter id")
1577 }
1578 if Dir == tp_pb.Direction_UPSTREAM {
1579 return "upstream", nil
1580 } else if Dir == tp_pb.Direction_DOWNSTREAM {
1581 return "downstream", nil
1582 }
1583 return "", nil
1584}
1585
1586func (f *OpenOltFlowMgr) checkAndAddFlow(args map[string]uint32, classifierInfo map[string]interface{},
1587 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, gemPort, intfID, onuID, uniID, portNo uint32,
1588 TpInst *tp.TechProfile, allocID []uint32, gemPorts []uint32, TpID uint32, uni string) {
1589 if ipProto, ok := classifierInfo[IPProto]; ok {
1590 if ipProto.(uint32) == IPProtoDhcp {
1591 log.Info("Adding DHCP flow")
1592 if pcp, ok := classifierInfo[VlanPcp]; ok {
1593 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1594 tp_pb.Direction_UPSTREAM,
1595 pcp.(uint32))
1596 //Adding DHCP upstream flow
1597 f.addDHCPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
1598 } else {
1599 //Adding DHCP upstream flow to all gemports
1600 installFlowOnAllGemports(f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, DhcpFlow)
1601 }
1602
1603 } else if ipProto == IgmpProto {
1604 log.Info("igmp flow add ignored, not implemented yet")
1605 return
1606 } else {
1607 log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
1608 return
1609 }
1610 } else if ethType, ok := classifierInfo[EthType]; ok {
1611 if ethType.(uint32) == EapEthType {
1612 log.Info("Adding EAPOL flow")
1613 var vlanID uint32
1614 if val, ok := classifierInfo[VlanVid]; ok {
1615 vlanID = (val.(uint32)) & VlanvIDMask
1616 } else {
1617 vlanID = DefaultMgmtVlan
1618 }
1619 if pcp, ok := classifierInfo[VlanPcp]; ok {
1620 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1621 tp_pb.Direction_UPSTREAM,
1622 pcp.(uint32))
1623
1624 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID[0], gemPort, vlanID)
1625 } else {
1626 installFlowOnAllGemports(nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, EapolFlow, vlanID)
1627 }
1628 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001629 } else if _, ok := actionInfo[PushVlan]; ok {
1630 log.Info("Adding upstream data rule")
1631 if pcp, ok := classifierInfo[VlanPcp]; ok {
1632 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1633 tp_pb.Direction_UPSTREAM,
1634 pcp.(uint32))
1635 //Adding HSIA upstream flow
1636 f.addUpstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
1637 } else {
1638 //Adding HSIA upstream flow to all gemports
1639 installFlowOnAllGemports(f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1640 }
1641 } else if _, ok := actionInfo[PopVlan]; ok {
1642 log.Info("Adding Downstream data rule")
1643 if pcp, ok := classifierInfo[VlanPcp]; ok {
1644 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05001645 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001646 pcp.(uint32))
1647 //Adding HSIA downstream flow
1648 f.addDownstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
1649 } else {
1650 //Adding HSIA downstream flow to all gemports
1651 installFlowOnAllGemports(f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1652 }
1653 } else {
1654 log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
1655 return
1656 }
1657 // Send Techprofile download event to child device in go routine as it takes time
1658 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, TpID)
1659}
1660
1661func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07001662 for _, field := range flows.GetOfbFields(flow) {
1663 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001664 classifierInfo[EthType] = field.GetEthType()
1665 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001666 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001667 classifierInfo[IPProto] = field.GetIpProto()
1668 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001669 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001670 classifierInfo[InPort] = field.GetPort()
1671 log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001672 } else if field.Type == flows.VLAN_VID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001673 classifierInfo[VlanVid] = field.GetVlanVid()
1674 log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001675 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001676 classifierInfo[VlanPcp] = field.GetVlanPcp()
1677 log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001678 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001679 classifierInfo[UDPDst] = field.GetUdpDst()
1680 log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001681 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001682 classifierInfo[UDPSrc] = field.GetUdpSrc()
1683 log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001684 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001685 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
1686 log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001687 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001688 classifierInfo[Ipv4Src] = field.GetIpv4Src()
1689 log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001690 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001691 classifierInfo[Metadata] = field.GetTableMetadata()
1692 log.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07001693 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001694 classifierInfo[TunnelID] = field.GetTunnelId()
1695 log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
1696 } else {
1697 log.Errorw("Un supported field type", log.Fields{"type": field.Type})
1698 return
1699 }
1700 }
1701}
1702
1703func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07001704 for _, action := range flows.GetActions(flow) {
1705 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001706 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001707 actionInfo[Output] = out.GetPort()
1708 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001709 } else {
1710 log.Error("Invalid output port in action")
1711 return errors.New("invalid output port in action")
1712 }
Scott Baker355d1742019-10-24 10:57:52 -07001713 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001714 actionInfo[PopVlan] = true
1715 log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001716 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001717 if out := action.GetPush(); out != nil {
1718 if tpid := out.GetEthertype(); tpid != 0x8100 {
1719 log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
1720 } else {
1721 actionInfo[PushVlan] = true
1722 actionInfo[TPID] = tpid
1723 log.Debugw("action-type-push-vlan",
1724 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
1725 }
1726 }
Scott Baker355d1742019-10-24 10:57:52 -07001727 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001728 if out := action.GetSetField(); out != nil {
1729 if field := out.GetField(); field != nil {
1730 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
1731 log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
1732 return errors.New("invalid openflow class")
1733 }
1734 /*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
1735 if ofbField := field.GetOfbField(); ofbField != nil {
1736 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
1737 if vlan := ofbField.GetVlanVid(); vlan != 0 {
1738 actionInfo[VlanVid] = vlan & 0xfff
1739 log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
1740 } else {
1741 log.Error("No Invalid vlan id in set vlan-vid action")
1742 }
1743 } else {
1744 log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
1745 }
1746 }
1747 }
1748 }
1749 } else {
1750 log.Errorw("Un supported action type", log.Fields{"type": action.Type})
1751 return errors.New("un supported action type")
1752 }
1753 }
1754 return nil
1755}
1756
1757func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001758 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001759 log.Debug("Controller bound trap flows, getting inport from tunnelid")
1760 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
1761 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001762 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001763 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07001764 log.Debugw("upstream pon-to-controller-flow,inport-in-tunnelid", log.Fields{"newInPort": classifierInfo[InPort].(uint32), "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001765 } else {
1766 log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1767 return errors.New("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1768 }
1769 }
1770 } else {
1771 log.Debug("Non-Controller flows, getting uniport from tunnelid")
1772 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07001773 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001774 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001775 actionInfo[Output] = uniPort
1776 log.Debugw("downstream-nni-to-pon-port-flow, outport-in-tunnelid", log.Fields{"newOutPort": actionInfo[Output].(uint32), "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001777 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001778 log.Debug("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid", log.Fields{"InPort": classifierInfo[InPort].(uint32), "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001779 return errors.New("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid")
1780 }
1781 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
1782 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001783 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001784 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07001785 log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[Output].(uint32),
1786 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001787 } else {
1788 log.Debug("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid", log.Fields{"InPort": classifierInfo[InPort].(uint32),
David K. Bainbridge82efc492019-09-04 09:57:11 -07001789 "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001790 return errors.New("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid")
1791 }
1792 }
1793 }
1794 return nil
1795}