blob: 97664849acb50558fdafafd9edaf6158ab52517d [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
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400554 // vlan_vid is a uint32. must be type asserted as such or conversion fails
555 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530556 if ok {
557 downlinkAction[VlanVid] = dlClVid & 0xfff
558 } else {
559 log.Error("dl-classifier-vid-type-conversion-failed")
560 return
561 }
562
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700563 f.addHSIAFlow(intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700564 Downstream, logicalFlow, allocID, gemportID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530565}
566
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700567func (f *OpenOltFlowMgr) addHSIAFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +0530568 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700569 allocID uint32, gemPortID uint32) {
Manikkaraj k884c1242019-04-11 16:26:42 +0530570 /* One of the OLT platform (Broadcom BAL) requires that symmetric
571 flows require the same flow_id to be used across UL and DL.
572 Since HSIA flow is the only symmetric flow currently, we need to
573 re-use the flow_id across both direction. The 'flow_category'
574 takes priority over flow_cookie to find any available HSIA_FLOW
575 id for the ONU.
576 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700577 log.Debugw("Adding HSIA flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "classifier": classifier,
578 "action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530579 "logicalFlow": *logicalFlow})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000580 var vlanPit uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400581 if _, ok := classifier[VlanPcp]; ok {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000582 vlanPit = classifier[VlanPcp].(uint32)
583 log.Debugw("Found pbit in the flow", log.Fields{"vlan_pit": vlanPit})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400584 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700585 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000586 flowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, HsiaFlow, vlanPit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530587 if err != nil {
588 log.Errorw("Flow id unavailable for HSIA flow", log.Fields{"direction": direction})
589 return
590 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700591 var classifierProto *openoltpb2.Classifier
592 var actionProto *openoltpb2.Action
Manikkaraj k884c1242019-04-11 16:26:42 +0530593 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
594 log.Error("Error in making classifier protobuf for hsia flow")
595 return
596 }
597 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
598 if actionProto = makeOpenOltActionField(action); actionProto == nil {
599 log.Errorw("Error in making action protobuf for hsia flow", log.Fields{"direction": direction})
600 return
601 }
602 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700603 networkIntfID := f.deviceHandler.nniIntfID
604 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
605 OnuId: int32(onuID),
606 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000607 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530608 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700609 AllocId: int32(allocID),
610 NetworkIntfId: int32(networkIntfID),
611 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530612 Classifier: classifierProto,
613 Action: actionProto,
614 Priority: int32(logicalFlow.Priority),
615 Cookie: logicalFlow.Cookie,
616 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400617 if ok := f.addFlowToDevice(logicalFlow, &flow); ok {
Manikkaraj k884c1242019-04-11 16:26:42 +0530618 log.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000619 flowsToKVStore := f.getUpdatedFlowInfo(&flow, flowStoreCookie, HsiaFlow, flowID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530620 if err := f.updateFlowInfoToKVStore(flow.AccessIntfId,
621 flow.OnuId,
622 flow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400623 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530624 log.Errorw("Error uploading HSIA flow into KV store", log.Fields{"flow": flow, "direction": direction, "error": err})
625 return
626 }
627 }
628}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700629func (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 +0530630
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700631 var dhcpFlow openoltpb2.Flow
632 var actionProto *openoltpb2.Action
633 var classifierProto *openoltpb2.Classifier
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530634
635 // Clear the action map
636 for k := range action {
637 delete(action, k)
638 }
639
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700640 action[TrapToHost] = true
641 classifier[UDPSrc] = uint32(68)
642 classifier[UDPDst] = uint32(67)
643 classifier[PacketTagType] = SingleTag
644 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530645
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700646 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530647
Manikkaraj kb1d51442019-07-23 10:41:02 -0400648 flowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, "", 0 /*classifier[VLAN_PCP].(uint32)*/)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530649
650 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700651 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530652 return
653 }
654
655 log.Debugw("Creating UL DHCP flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID})
656
657 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
658 log.Error("Error in making classifier protobuf for ul flow")
659 return
660 }
661 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
662 if actionProto = makeOpenOltActionField(action); actionProto == nil {
663 log.Error("Error in making action protobuf for ul flow")
664 return
665 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700666 networkIntfID := f.deviceHandler.nniIntfID
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530667
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700668 dhcpFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
669 OnuId: int32(onuID),
670 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530671 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700672 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700673 AllocId: int32(allocID),
674 NetworkIntfId: int32(networkIntfID),
675 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530676 Classifier: classifierProto,
677 Action: actionProto,
678 Priority: int32(logicalFlow.Priority),
679 Cookie: logicalFlow.Cookie,
680 PortNo: portNo}
681
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400682 if ok := f.addFlowToDevice(logicalFlow, &dhcpFlow); ok {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530683 log.Debug("DHCP UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400684 flowsToKVStore := f.getUpdatedFlowInfo(&dhcpFlow, flowStoreCookie, "DHCP", flowID)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530685 if err := f.updateFlowInfoToKVStore(dhcpFlow.AccessIntfId,
686 dhcpFlow.OnuId,
687 dhcpFlow.UniId,
688 dhcpFlow.FlowId, flowsToKVStore); err != nil {
689 log.Errorw("Error uploading DHCP UL flow into KV store", log.Fields{"flow": dhcpFlow, "error": err})
690 return
691 }
692 }
693
manikkaraj kbf256be2019-03-25 00:13:48 +0530694 return
695}
696
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700697// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
698func (f *OpenOltFlowMgr) addEAPOLFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, vlanID uint32) {
699 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 +0530700
701 uplinkClassifier := make(map[string]interface{})
702 uplinkAction := make(map[string]interface{})
703 downlinkClassifier := make(map[string]interface{})
704 downlinkAction := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700705 var upstreamFlow openoltpb2.Flow
706 var downstreamFlow openoltpb2.Flow
manikkaraj kbf256be2019-03-25 00:13:48 +0530707
708 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700709 uplinkClassifier[EthType] = uint32(EapEthType)
710 uplinkClassifier[PacketTagType] = SingleTag
711 uplinkClassifier[VlanVid] = vlanID
manikkaraj kbf256be2019-03-25 00:13:48 +0530712 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700713 uplinkAction[TrapToHost] = true
714 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530715 //Add Uplink EAPOL Flow
Manikkaraj kb1d51442019-07-23 10:41:02 -0400716 uplinkFlowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530717 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700718 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manikkaraj k884c1242019-04-11 16:26:42 +0530719 return
manikkaraj kbf256be2019-03-25 00:13:48 +0530720 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700721 var classifierProto *openoltpb2.Classifier
722 var actionProto *openoltpb2.Action
723 log.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530724
725 if classifierProto = makeOpenOltClassifierField(uplinkClassifier); classifierProto == nil {
726 log.Error("Error in making classifier protobuf for ul flow")
727 return
728 }
729 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
730 if actionProto = makeOpenOltActionField(uplinkAction); actionProto == nil {
731 log.Error("Error in making action protobuf for ul flow")
732 return
733 }
734 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700735 networkIntfID := f.deviceHandler.nniIntfID
736 upstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
737 OnuId: int32(onuID),
738 UniId: int32(uniID),
739 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700740 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700741 AllocId: int32(allocID),
742 NetworkIntfId: int32(networkIntfID),
743 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530744 Classifier: classifierProto,
745 Action: actionProto,
746 Priority: int32(logicalFlow.Priority),
747 Cookie: logicalFlow.Cookie,
748 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400749 if ok := f.addFlowToDevice(logicalFlow, &upstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530750 log.Debug("EAPOL UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400751 flowCategory := "EAPOL"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700752 flowsToKVStore := f.getUpdatedFlowInfo(&upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530753 if err := f.updateFlowInfoToKVStore(upstreamFlow.AccessIntfId,
754 upstreamFlow.OnuId,
755 upstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400756 upstreamFlow.FlowId,
757 /* lowCategory, */
758 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530759 log.Errorw("Error uploading EAPOL UL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
760 return
761 }
762 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400763 // Dummy Downstream flow due to BAL 2.6 limitation
764 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530765 /* Add Downstream EAPOL Flow, Only for first EAP flow (BAL
766 # requirement)
767 # On one of the platforms (Broadcom BAL), when same DL classifier
768 # vlan was used across multiple ONUs, eapol flow re-adds after
769 # flow delete (cases of onu reboot/disable) fails.
770 # In order to generate unique vlan, a combination of intf_id
771 # onu_id and uniId is used.
772 # uniId defaults to 0, so add 1 to it.
773 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700774 log.Debugw("Creating DL EAPOL flow with default vlan", log.Fields{"vlan": vlanID})
775 specialVlanDlFlow := 4090 - intfID*onuID*(uniID+1)
manikkaraj kbf256be2019-03-25 00:13:48 +0530776 // Assert that we do not generate invalid vlans under no condition
777 if specialVlanDlFlow <= 2 {
778 log.Fatalw("invalid-vlan-generated", log.Fields{"vlan": specialVlanDlFlow})
779 return
780 }
781 log.Debugw("specialVlanEAPOLDlFlow:", log.Fields{"dl_vlan": specialVlanDlFlow})
782 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700783 downlinkClassifier[PacketTagType] = SingleTag
Manikkaraj kb1d51442019-07-23 10:41:02 -0400784 downlinkClassifier[EthType] = uint32(EapEthType)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700785 downlinkClassifier[VlanVid] = uint32(specialVlanDlFlow)
manikkaraj kbf256be2019-03-25 00:13:48 +0530786 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700787 downlinkAction[PushVlan] = true
788 downlinkAction[VlanVid] = vlanID
789 flowStoreCookie := getFlowStoreCookie(downlinkClassifier, gemPortID)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000790 downlinkFlowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530791 if err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530792 log.Errorw("flowId unavailable for DL EAPOL",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700793 log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
manikkaraj kbf256be2019-03-25 00:13:48 +0530794 return
795 }
796 log.Debugw("Creating DL EAPOL flow",
salmansiddiqui7ac62132019-08-22 03:58:50 +0000797 log.Fields{"dl_classifier": downlinkClassifier, "dl_action": downlinkAction, "downlinkFlowID": downlinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530798 if classifierProto = makeOpenOltClassifierField(downlinkClassifier); classifierProto == nil {
799 log.Error("Error in making classifier protobuf for downlink flow")
800 return
801 }
802 if actionProto = makeOpenOltActionField(downlinkAction); actionProto == nil {
803 log.Error("Error in making action protobuf for dl flow")
804 return
805 }
806 // Downstream flow in grpc protobuf
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700807 downstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
808 OnuId: int32(onuID),
809 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000810 FlowId: downlinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700811 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700812 AllocId: int32(allocID),
813 NetworkIntfId: int32(networkIntfID),
814 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530815 Classifier: classifierProto,
816 Action: actionProto,
817 Priority: int32(logicalFlow.Priority),
818 Cookie: logicalFlow.Cookie,
819 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400820 if ok := f.addFlowToDevice(logicalFlow, &downstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530821 log.Debug("EAPOL DL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400822 flowCategory := ""
salmansiddiqui7ac62132019-08-22 03:58:50 +0000823 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamFlow, flowStoreCookie, flowCategory, downlinkFlowID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530824 if err := f.updateFlowInfoToKVStore(downstreamFlow.AccessIntfId,
825 downstreamFlow.OnuId,
826 downstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400827 downstreamFlow.FlowId,
828 /* flowCategory, */
829 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530830 log.Errorw("Error uploading EAPOL DL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
831 return
832 }
833 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530834 }
835 log.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
836}
837
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700838func makeOpenOltClassifierField(classifierInfo map[string]interface{}) *openoltpb2.Classifier {
839 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -0700840
841 classifier.EthType, _ = classifierInfo[EthType].(uint32)
842 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
843 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
844 vid := vlanID & VlanvIDMask
845 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -0400846 classifier.OVid = vid
847 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530848 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700849 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
850 vid := uint32(metadata)
851 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -0400852 classifier.IVid = vid
853 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530854 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700855 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400856 if vlanPcp == 0 {
857 classifier.OPbits = VlanPCPMask
858 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700859 classifier.OPbits = vlanPcp & VlanPCPMask
Manikkaraj kb1d51442019-07-23 10:41:02 -0400860 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530861 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700862 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
863 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
864 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
865 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
866 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
867 classifier.PktTagType = pktTagType
868
869 switch pktTagType {
870 case SingleTag:
871 case DoubleTag:
872 case Untagged:
873 default:
manikkaraj kbf256be2019-03-25 00:13:48 +0530874 log.Error("Invalid tag type in classifier") // should not hit
875 return nil
876 }
877 }
878 return &classifier
879}
880
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700881func makeOpenOltActionField(actionInfo map[string]interface{}) *openoltpb2.Action {
882 var actionCmd openoltpb2.ActionCmd
883 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +0530884 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700885 if _, ok := actionInfo[PopVlan]; ok {
886 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530887 action.Cmd.RemoveOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700888 } else if _, ok := actionInfo[PushVlan]; ok {
889 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530890 action.Cmd.AddOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700891 } else if _, ok := actionInfo[TrapToHost]; ok {
892 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +0530893 } else {
894 log.Errorw("Invalid-action-field", log.Fields{"action": actionInfo})
895 return nil
896 }
897 return &action
898}
899
Manikkaraj kb1d51442019-07-23 10:41:02 -0400900func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uni string, TpID uint32) string {
901 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530902}
903
Devmalya Paul495b94a2019-08-27 19:42:00 -0400904// DeleteTechProfileInstance removes the tech profile instance from persistent storage
905func (f *OpenOltFlowMgr) DeleteTechProfileInstance(intfID uint32, onuID uint32, uniID uint32, sn string) error {
906 tpID := f.resourceMgr.GetTechProfileIDForOnu(intfID, onuID, uniID)
907 uniPortName := fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
908 if err := f.techprofile[intfID].DeleteTechProfileInstance(tpID, uniPortName); err != nil {
909 log.Debugw("Failed-to-delete-tp-instance-from-kv-store", log.Fields{"tp-id": tpID, "uni-port-name": uniPortName})
910 return err
911 }
912 return nil
913}
914
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700915func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530916 if len(classifier) == 0 { // should never happen
917 log.Error("Invalid classfier object")
918 return 0
919 }
920 var jsonData []byte
921 var flowString string
922 var err error
923 // TODO: Do we need to marshall ??
924 if jsonData, err = json.Marshal(classifier); err != nil {
925 log.Error("Failed to encode classifier")
926 return 0
927 }
928 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700929 if gemPortID != 0 {
930 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +0530931 }
932 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700933 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +0530934 hash := big.NewInt(0)
935 hash.SetBytes(h.Sum(nil))
936 return hash.Uint64()
937}
938
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700939func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openoltpb2.Flow, flowStoreCookie uint64, flowCategory string, deviceFlowID uint32) *[]rsrcMgr.FlowInfo {
940 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
941 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400942 /* For flows which trap out of the NNI, the AccessIntfId is invalid
943 (set to -1). In such cases, we need to refer to the NetworkIntfId .
944 */
945 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700946 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400947 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700948 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400949 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700950 // Get existing flows matching flowid for given subscriber from KV store
951 existingFlows := f.resourceMgr.GetFlowIDInfo(intfID, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -0400952 if existingFlows != nil {
953 log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700954 //for _, f := range *existingFlows {
955 // flows = append(flows, f)
956 //}
957 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -0400958 }
959 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 +0530960 return &flows
961}
962
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400963//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
964// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
965// var intfId uint32
966// /* For flows which trap out of the NNI, the AccessIntfId is invalid
967// (set to -1). In such cases, we need to refer to the NetworkIntfId .
968// */
969// if flow.AccessIntfId != -1 {
970// intfId = uint32(flow.AccessIntfId)
971// } else {
972// intfId = uint32(flow.NetworkIntfId)
973// }
974// // Get existing flows matching flowid for given subscriber from KV store
975// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
976// if existingFlows != nil {
977// log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
978// for _, f := range *existingFlows {
979// flows = append(flows, f)
980// }
981// }
982// log.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
983// return &flows
984//}
985
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700986func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
manikkaraj k17652a72019-05-06 09:06:36 -0400987 log.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700988 if err := f.resourceMgr.UpdateFlowIDInfo(intfID, onuID, uniID, flowID, flows); err != nil {
manikkaraj k17652a72019-05-06 09:06:36 -0400989 log.Debug("Error while Storing flow into KV store")
990 return err
991 }
992 log.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +0530993 return nil
994}
995
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700996func (f *OpenOltFlowMgr) addFlowToDevice(logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) bool {
Daniele Rossi22db98e2019-07-11 11:50:00 +0000997
998 var intfID uint32
999 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1000 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1001 */
1002 if deviceFlow.AccessIntfId != -1 {
1003 intfID = uint32(deviceFlow.AccessIntfId)
1004 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001005 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001006 intfID = uint32(deviceFlow.NetworkIntfId)
1007 }
1008
manikkaraj kbf256be2019-03-25 00:13:48 +05301009 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1010 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001011
1012 st, _ := status.FromError(err)
1013 if st.Code() == codes.AlreadyExists {
1014 log.Debug("Flow already exixts", log.Fields{"err": err, "deviceFlow": deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301015 return false
1016 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001017
1018 if err != nil {
1019 log.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": deviceFlow})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001020 f.resourceMgr.FreeFlowID(intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001021 return false
1022 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001023 log.Debugw("Flow added to device successfully ", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001024 f.registerFlow(logicalFlow, deviceFlow)
1025 return true
1026}
1027
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001028func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) bool {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001029 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1030 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1031 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001032 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
1033 log.Warnw("Can not remove flow from device since it's unreachable", log.Fields{"err": err, "deviceFlow": deviceFlow})
1034 //Assume the flow is removed
1035 return true
1036 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001037 log.Errorw("Failed to Remove flow from device", log.Fields{"err": err, "deviceFlow": deviceFlow})
1038 return false
serkant.uluderya245caba2019-09-24 23:15:29 -07001039
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001040 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001041 log.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301042 return true
1043}
1044
1045/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1046 //update core flows_proxy : flows_proxy.update('/', flows)
1047}
1048
1049func generateStoredId(flowId uint32, direction string)uint32{
1050
David K. Bainbridge82efc492019-09-04 09:57:11 -07001051 if direction == Upstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301052 log.Debug("Upstream flow shifting flowid")
1053 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001054 }else if direction == Downstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301055 log.Debug("Downstream flow not shifting flowid")
1056 return flowId
1057 }else{
1058 log.Errorw("Unrecognized direction",log.Fields{"direction": direction})
1059 return flowId
1060 }
1061}
1062
1063*/
1064
Humera Kouser94d7a842019-08-25 19:04:32 -04001065func (f *OpenOltFlowMgr) addLLDPFlow(flow *ofp.OfpFlowStats, portNo uint32) {
1066
1067 classifierInfo := make(map[string]interface{})
1068 actionInfo := make(map[string]interface{})
1069
1070 classifierInfo[EthType] = uint32(LldpEthType)
1071 classifierInfo[PacketTagType] = Untagged
1072 actionInfo[TrapToHost] = true
1073
1074 // LLDP flow is installed to trap LLDP packets on the NNI port.
1075 // We manage flow_id resource pool on per PON port basis.
1076 // Since this situation is tricky, as a hack, we pass the NNI port
1077 // index (network_intf_id) as PON port Index for the flow_id resource
1078 // pool. Also, there is no ONU Id available for trapping LLDP packets
1079 // on NNI port, use onu_id as -1 (invalid)
1080 // ****************** CAVEAT *******************
1081 // This logic works if the NNI Port Id falls within the same valid
1082 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1083 // we need to have a re-look at this.
1084 // *********************************************
1085
1086 var onuID = -1
1087 var uniID = -1
1088 var gemPortID = -1
1089
1090 var networkInterfaceID = IntfIDFromNniPortNum(portNo)
1091 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
1092 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), flowStoreCookie); present {
1093 log.Debug("Flow-exists--not-re-adding")
1094 return
1095 }
1096 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
1097
1098 if err != nil {
1099 log.Errorw("Flow id unavailable for LLDP traponNNI flow", log.Fields{"error": err})
1100 return
1101 }
1102 var classifierProto *openoltpb2.Classifier
1103 var actionProto *openoltpb2.Action
1104 if classifierProto = makeOpenOltClassifierField(classifierInfo); classifierProto == nil {
1105 log.Error("Error in making classifier protobuf for LLDP trap on nni flow")
1106 return
1107 }
1108 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1109 if actionProto = makeOpenOltActionField(actionInfo); actionProto == nil {
1110 log.Error("Error in making action protobuf for LLDP trap on nni flow")
1111 return
1112 }
1113 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
1114
1115 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1116 OnuId: int32(onuID), // OnuId not required
1117 UniId: int32(uniID), // UniId not used
1118 FlowId: flowID,
1119 FlowType: Downstream,
1120 NetworkIntfId: int32(networkInterfaceID),
1121 GemportId: int32(gemPortID),
1122 Classifier: classifierProto,
1123 Action: actionProto,
1124 Priority: int32(flow.Priority),
1125 Cookie: flow.Cookie,
1126 PortNo: portNo}
1127 if ok := f.addFlowToDevice(flow, &downstreamflow); ok {
1128 log.Debug("LLDP trap on NNI flow added to device successfully")
1129 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID)
1130 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1131 int32(onuID),
1132 int32(uniID),
1133 flowID, flowsToKVStore); err != nil {
1134 log.Errorw("Error uploading LLDP flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1135 }
1136 }
1137 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301138}
1139
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001140func getUniPortPath(intfID uint32, onuID uint32, uniID uint32) string {
1141 return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1142}
1143
1144//getOnuChildDevice to fetch onu
1145func (f *OpenOltFlowMgr) getOnuChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
1146 log.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
1147 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
1148 onuDevice := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301149 if onuDevice == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001150 log.Errorw("onu not found", log.Fields{"intfId": parentPortNo, "onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301151 return nil, errors.New("onu not found")
manikkaraj kbf256be2019-03-25 00:13:48 +05301152 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301153 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1154 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301155}
1156
1157func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001158 log.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301159 return nil
1160}
1161
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001162func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
1163 log.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301164}
1165
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001166func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001167 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001168 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001169 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001170 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001171}
1172
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001173func (f *OpenOltFlowMgr) clearFlowFromResourceManager(flow *ofp.OfpFlowStats, flowID uint32, flowDirection string) {
1174 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowID": flowID, "flowDirection": flowDirection, "flow": *flow})
Humera Kouser94d7a842019-08-25 19:04:32 -04001175 portNum, ponIntf, onuID, uniID, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001176 if err != nil {
1177 log.Error(err)
1178 return
1179 }
1180 log.Debugw("Extracted access info from flow to be deleted",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001181 log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001182
Humera Kouser94d7a842019-08-25 19:04:32 -04001183 if ethType == LldpEthType {
1184 var networkInterfaceID uint32
1185 var onuID = -1
1186 var uniID = -1
1187
1188 networkInterfaceID = IntfIDFromNniPortNum(inPort)
1189 f.resourceMgr.FreeFlowID(networkInterfaceID, int32(onuID), int32(uniID), flowID)
1190 return
1191 }
1192
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001193 flowsInfo := f.resourceMgr.GetFlowIDInfo(ponIntf, onuID, uniID, flowID)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001194 if flowsInfo == nil {
1195 log.Debugw("No FlowInfo found found in KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001196 log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001197 return
1198 }
1199 var updatedFlows []rsrcMgr.FlowInfo
1200
1201 for _, flow := range *flowsInfo {
1202 updatedFlows = append(updatedFlows, flow)
1203 }
1204
1205 for i, storedFlow := range updatedFlows {
1206 if flowDirection == storedFlow.Flow.FlowType {
1207 //Remove the Flow from FlowInfo
1208 log.Debugw("Removing flow to be deleted", log.Fields{"flow": storedFlow})
1209 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1210 break
1211 }
1212 }
1213
1214 if len(updatedFlows) >= 0 {
1215 // There are still flows referencing the same flow_id.
1216 // So the flow should not be freed yet.
1217 // For ex: Case of HSIA where same flow is shared
1218 // between DS and US.
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001219 f.updateFlowInfoToKVStore(int32(ponIntf), int32(onuID), int32(uniID), flowID, &updatedFlows)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001220 if len(updatedFlows) == 0 {
1221 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 -04001222 f.resourceMgr.FreeFlowID(ponIntf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001223 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001224 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001225 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ponIntf, onuID, uniID)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001226 if len(flowIds) == 0 {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001227 log.Debugf("Flow count for subscriber %d is zero", onuID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001228 kvstoreTpID := f.resourceMgr.GetTechProfileIDForOnu(ponIntf, onuID, uniID)
1229 if kvstoreTpID == 0 {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001230 log.Warnw("Could-not-find-techprofile-tableid-for-uni", log.Fields{"ponIntf": ponIntf, "onuId": onuID, "uniId": uniID})
1231 return
1232 }
1233 uni := getUniPortPath(ponIntf, onuID, uniID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001234 tpPath := f.getTPpath(ponIntf, uni, kvstoreTpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001235 log.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001236 techprofileInst, err := f.techprofile[ponIntf].GetTPInstanceFromKVStore(kvstoreTpID, tpPath)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001237 if err != nil { // This should not happen, something wrong in KV backend transaction
1238 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": 20, "path": tpPath})
1239 return
1240 }
1241 if techprofileInst == nil {
1242 log.Errorw("Tech-profile-instance-does-not-exist-in-KV Store", log.Fields{"tpPath": tpPath})
1243 return
1244 }
1245
1246 f.RemoveSchedulerQueues(tp_pb.Direction_UPSTREAM, ponIntf, onuID, uniID, portNum, techprofileInst)
1247 f.RemoveSchedulerQueues(tp_pb.Direction_DOWNSTREAM, ponIntf, onuID, uniID, portNum, techprofileInst)
1248 } else {
1249 log.Debugf("Flow ids for subscriber", log.Fields{"onu": onuID, "flows": flowIds})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001250 }
1251}
1252
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001253//RemoveFlow removes the flow from the device
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001254func (f *OpenOltFlowMgr) RemoveFlow(flow *ofp.OfpFlowStats) {
1255 log.Debugw("Removing Flow", log.Fields{"flow": flow})
1256 var deviceFlowsToRemove []ofp.OfpFlowStats
1257 var deletedFlowsIdx []int
1258 for _, curFlow := range f.storedDeviceFlows {
1259 if curFlow.Cookie == flow.Id {
1260 log.Debugw("Found found matching flow-cookie", log.Fields{"curFlow": curFlow})
1261 deviceFlowsToRemove = append(deviceFlowsToRemove, curFlow)
1262 }
1263 }
1264 log.Debugw("Flows to be deleted", log.Fields{"deviceFlowsToRemove": deviceFlowsToRemove})
1265 for index, curFlow := range deviceFlowsToRemove {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001266 id, direction := f.decodeStoredID(curFlow.GetId())
1267 removeFlowMessage := openoltpb2.Flow{FlowId: uint32(id), FlowType: direction}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001268 if ok := f.removeFlowFromDevice(&removeFlowMessage); ok {
1269 log.Debug("Flow removed from device successfully")
1270 deletedFlowsIdx = append(deletedFlowsIdx, index)
1271 f.clearFlowFromResourceManager(flow, uint32(id), direction) //TODO: Take care of the limitations
1272 }
1273
1274 }
1275 // Can be done in separate go routine as it takes time ?
1276 for _, flowToRemove := range deletedFlowsIdx {
1277 for index, storedFlow := range f.storedDeviceFlows {
1278 if deviceFlowsToRemove[flowToRemove].Cookie == storedFlow.Cookie {
1279 log.Debugw("Removing flow from local Store", log.Fields{"flow": storedFlow})
1280 f.storedDeviceFlows = append(f.storedDeviceFlows[:index], f.storedDeviceFlows[index+1:]...)
1281 break
1282 }
1283 }
1284 }
1285 log.Debugw("Flows removed from the data store",
1286 log.Fields{"number_of_flows_removed": len(deviceFlowsToRemove), "updated_stored_flows": f.storedDeviceFlows})
1287 return
1288}
1289
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001290// AddFlow add flow to device
Manikkaraj kb1d51442019-07-23 10:41:02 -04001291func (f *OpenOltFlowMgr) AddFlow(flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001292 classifierInfo := make(map[string]interface{})
1293 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001294 var UsMeterID uint32
1295 var DsMeterID uint32
1296
1297 log.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001298 formulateClassifierInfoFromFlow(classifierInfo, flow)
1299
1300 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
1301 if err != nil {
1302 // Error logging is already done in the called function
1303 // So just return in case of error
1304 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301305 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001306
manikkaraj k17652a72019-05-06 09:06:36 -04001307 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00001308 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
1309 if err != nil {
1310 // error if any, already logged in the called function
1311 return
manikkaraj k17652a72019-05-06 09:06:36 -04001312 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001313
David K. Bainbridge82efc492019-09-04 09:57:11 -07001314 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[Output]})
1315 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00001316
Humera Kouser94d7a842019-08-25 19:04:32 -04001317 if ethType, ok := classifierInfo[EthType]; ok {
1318 if ethType.(uint32) == LldpEthType {
1319 log.Info("Adding LLDP flow")
1320 f.addLLDPFlow(flow, portNo)
1321 return
1322 }
1323 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001324 if ipProto, ok := classifierInfo[IPProto]; ok {
1325 if ipProto.(uint32) == IPProtoDhcp {
1326 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001327 if udpSrc.(uint32) == uint32(67) {
1328 log.Debug("trap-dhcp-from-nni-flow")
1329 f.addDHCPTrapFlowOnNNI(flow, classifierInfo, portNo)
1330 return
1331 }
1332 }
1333 }
1334 }
A R Karthick1f85b802019-10-11 05:06:05 +00001335
1336 f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
1337
Manikkaraj kb1d51442019-07-23 10:41:02 -04001338 /* Metadata 8 bytes:
1339 Most Significant 2 Bytes = Inner VLAN
1340 Next 2 Bytes = Tech Profile ID(TPID)
1341 Least Significant 4 Bytes = Port ID
David K. Bainbridge82efc492019-09-04 09:57:11 -07001342 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
Manikkaraj kb1d51442019-07-23 10:41:02 -04001343 subscriber related flows.
1344 */
Scott Baker355d1742019-10-24 10:57:52 -07001345 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001346 if metadata == 0 {
1347 log.Error("Metadata is not present in flow which is mandatory")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001348 return
1349 }
Scott Baker355d1742019-10-24 10:57:52 -07001350 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001351 kvstoreTpID := f.resourceMgr.GetTechProfileIDForOnu(intfID, onuID, uniID)
1352 if kvstoreTpID == 0 {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001353 log.Debugf("tpid-not-present-in-kvstore, using tp id %d from flow metadata", TpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001354 } else if kvstoreTpID != uint32(TpID) {
1355 log.Error(" Tech-profile-updates-not-supported", log.Fields{"Tpid-in-flow": TpID, "kvstore-TpId": kvstoreTpID})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001356 return
1357 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001358 log.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001359 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07001360 UsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001361 log.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
1362 } else {
Scott Baker355d1742019-10-24 10:57:52 -07001363 DsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001364 log.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
1365
1366 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001367 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001368}
1369
1370//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04001371func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001372
1373 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301374 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001375 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301376 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301377 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301378 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04001379
Manikkaraj kb1d51442019-07-23 10:41:02 -04001380 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001381 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
manikkaraj k17652a72019-05-06 09:06:36 -04001382 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
1383 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1384 tpDownloadMsg,
1385 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
1386 f.deviceHandler.deviceType,
1387 onuDevice.Type,
1388 onuDevice.Id,
1389 onuDevice.ProxyAddress.DeviceId, "")
1390 if sendErr != nil {
1391 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1392 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1393 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1394 return sendErr
1395 }
1396 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05301397 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301398}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001399
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001400//UpdateOnuInfo function adds onu info to cache
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001401func (f *OpenOltFlowMgr) UpdateOnuInfo(intfID uint32, onuID uint32, serialNum string) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001402 onu := onuInfo{intfID: intfID, onuID: onuID, serialNumber: serialNum}
1403 onuIDkey := onuIDKey{intfID: intfID, onuID: onuID}
William Kurkian740a09c2019-10-23 17:07:38 -04001404 f.onuIdsLock.Lock()
1405 defer f.onuIdsLock.Unlock()
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001406 f.onuIds[onuIDkey] = onu
1407 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
1408}
1409
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001410//addGemPortToOnuInfoMap function stores adds GEMport to ONU map
1411func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(intfID uint32, onuID uint32, gemPort uint32) {
1412 onuIDkey := onuIDKey{intfID: intfID, onuID: onuID}
William Kurkian740a09c2019-10-23 17:07:38 -04001413 f.onuIdsLock.RLock()
1414 defer f.onuIdsLock.RUnlock()
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001415 if val, ok := f.onuIds[onuIDkey]; ok {
kdarapu3248f9a2019-10-03 13:54:52 +05301416 onuInf := val
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001417 gemportKey := gemPortKey{intfID: intfID, gemPort: gemPort}
kdarapu3248f9a2019-10-03 13:54:52 +05301418 f.onuGemPortIds[gemportKey] = onuInf
1419 log.Debugw("Cached Gemport to Onuinfo map", log.Fields{"GemPort": gemPort, "intfId": onuInf.intfID, "onuId": onuInf.onuID})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001420 return
1421 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001422 log.Errorw("OnuInfo not found", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001423}
1424
1425// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001426
1427//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
1428func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
1429 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 -04001430 if serialNumber != "" {
kdarapu3248f9a2019-10-03 13:54:52 +05301431 if onuInf, ok := f.onuSerialNumbers[serialNumber]; ok {
1432 return onuInf.onuID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001433 }
1434 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001435 gemportKey := gemPortKey{intfID: intfID, gemPort: gemPortID}
kdarapu3248f9a2019-10-03 13:54:52 +05301436 if onuInf, ok := f.onuGemPortIds[gemportKey]; ok {
1437 log.Debugw("Retrieved onu info from access", log.Fields{"intfId": intfID, "gemPortId": gemPortID, "onuId": onuInf.onuID})
1438 return onuInf.onuID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001439 }
1440 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001441 log.Errorw("onuid is not found", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPort": gemPortID})
1442 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 -04001443}
1444
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001445//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
1446func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001447 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001448 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001449 var err error
1450
1451 if packetIn.IntfType == "pon" {
1452 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001453 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001454 log.Errorw("Unable to get ONU ID from GEM/PON port", log.Fields{"pon port": packetIn.IntfId, "gemport": packetIn.GemportId})
1455 return logicalPortNum, err
1456 }
1457 if packetIn.PortNo != 0 {
1458 logicalPortNum = packetIn.PortNo
1459 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001460 uniID := uint32(0) // FIXME - multi-uni support
1461 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001462 }
1463 // 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 -07001464 pktInkey := packetInInfoKey{intfID: packetIn.IntfId, onuID: onuID, logicalPort: logicalPortNum}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001465 f.packetInGemPort[pktInkey] = packetIn.GemportId
1466 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001467 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001468 }
1469 log.Debugw("Retrieved logicalport from packet-in", log.Fields{"logicalPortNum": logicalPortNum, "IntfType": packetIn.IntfType})
1470 return logicalPortNum, nil
1471}
1472
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001473//GetPacketOutGemPortID returns gemPortId
1474func (f *OpenOltFlowMgr) GetPacketOutGemPortID(intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
1475 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001476 var err error
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001477 key := packetInInfoKey{intfID: intfID, onuID: onuID, logicalPort: portNum}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001478 if val, ok := f.packetInGemPort[key]; ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001479 gemPortID = val
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001480 } else {
1481 log.Errorw("Key-Error while fetching packet-out GEM port", log.Fields{"key": key})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001482 err = errors.New("key-error while fetching packet-out GEM port")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001483 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001484 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001485}
1486
Manikkaraj kb1d51442019-07-23 10:41:02 -04001487func installFlowOnAllGemports(
1488 f1 func(intfId uint32, onuId uint32, uniId uint32,
1489 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
1490 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32),
1491 f2 func(intfId uint32, onuId uint32, uniId uint32, portNo uint32,
1492 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32),
1493 args map[string]uint32,
1494 classifier map[string]interface{}, action map[string]interface{},
1495 logicalFlow *ofp.OfpFlowStats,
1496 gemPorts []uint32,
1497 FlowType string,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001498 vlanID ...uint32) {
1499 log.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
1500 for _, gemPortID := range gemPorts {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001501 if FlowType == HsiaFlow || FlowType == DhcpFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001502 f1(args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001503 } else if FlowType == EapolFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001504 f2(args["intfId"], args["onuId"], args["uniId"], args["portNo"], logicalFlow, args["allocId"], gemPortID, vlanID[0])
Manikkaraj kb1d51442019-07-23 10:41:02 -04001505 } else {
1506 log.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
1507 return
1508 }
1509 }
1510}
1511
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001512func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
1513 log.Debug("Adding trap-dhcp-of-nni-flow")
1514 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001515 classifier[PacketTagType] = DoubleTag
1516 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001517 /* We manage flowId resource pool on per PON port basis.
1518 Since this situation is tricky, as a hack, we pass the NNI port
1519 index (network_intf_id) as PON port Index for the flowId resource
1520 pool. Also, there is no ONU Id available for trapping DHCP packets
1521 on NNI port, use onu_id as -1 (invalid)
1522 ****************** CAVEAT *******************
1523 This logic works if the NNI Port Id falls within the same valid
1524 range of PON Port Ids. If this doesn't work for some OLT Vendor
1525 we need to have a re-look at this.
1526 *********************************************
1527 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001528 onuID := -1
1529 uniID := -1
1530 gemPortID := -1
1531 allocID := -1
1532 networkInterfaceID := f.deviceHandler.nniIntfID
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001533 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001534 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), flowStoreCookie); present {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001535 log.Debug("Flow-exists--not-re-adding")
1536 return
1537 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001538 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001539 if err != nil {
1540 log.Errorw("Flow id unavailable for DHCP traponNNI flow", log.Fields{"error": err})
1541 return
1542 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001543 var classifierProto *openoltpb2.Classifier
1544 var actionProto *openoltpb2.Action
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001545 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
1546 log.Error("Error in making classifier protobuf for dhcp trap on nni flow")
1547 return
1548 }
1549 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1550 if actionProto = makeOpenOltActionField(action); actionProto == nil {
1551 log.Error("Error in making action protobuf for dhcp trap on nni flow")
1552 return
1553 }
1554 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001555 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1556 OnuId: int32(onuID), // OnuId not required
1557 UniId: int32(uniID), // UniId not used
1558 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001559 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001560 AllocId: int32(allocID), // AllocId not used
1561 NetworkIntfId: int32(networkInterfaceID),
1562 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001563 Classifier: classifierProto,
1564 Action: actionProto,
1565 Priority: int32(logicalFlow.Priority),
1566 Cookie: logicalFlow.Cookie,
1567 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001568 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001569 log.Debug("DHCP trap on NNI flow added to device successfully")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001570 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID)
1571 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1572 int32(onuID),
1573 int32(uniID),
1574 flowID, flowsToKVStore); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001575 log.Errorw("Error uploading DHCP DL flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1576 }
1577 }
1578 return
1579}
salmansiddiqui7ac62132019-08-22 03:58:50 +00001580
1581func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
1582 if MeterID == 0 { // This should never happen
1583 log.Error("Invalid meter id")
1584 return "", errors.New("invalid meter id")
1585 }
1586 if Dir == tp_pb.Direction_UPSTREAM {
1587 return "upstream", nil
1588 } else if Dir == tp_pb.Direction_DOWNSTREAM {
1589 return "downstream", nil
1590 }
1591 return "", nil
1592}
1593
1594func (f *OpenOltFlowMgr) checkAndAddFlow(args map[string]uint32, classifierInfo map[string]interface{},
1595 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, gemPort, intfID, onuID, uniID, portNo uint32,
1596 TpInst *tp.TechProfile, allocID []uint32, gemPorts []uint32, TpID uint32, uni string) {
1597 if ipProto, ok := classifierInfo[IPProto]; ok {
1598 if ipProto.(uint32) == IPProtoDhcp {
1599 log.Info("Adding DHCP flow")
1600 if pcp, ok := classifierInfo[VlanPcp]; ok {
1601 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1602 tp_pb.Direction_UPSTREAM,
1603 pcp.(uint32))
1604 //Adding DHCP upstream flow
1605 f.addDHCPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
1606 } else {
1607 //Adding DHCP upstream flow to all gemports
1608 installFlowOnAllGemports(f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, DhcpFlow)
1609 }
1610
1611 } else if ipProto == IgmpProto {
1612 log.Info("igmp flow add ignored, not implemented yet")
1613 return
1614 } else {
1615 log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
1616 return
1617 }
1618 } else if ethType, ok := classifierInfo[EthType]; ok {
1619 if ethType.(uint32) == EapEthType {
1620 log.Info("Adding EAPOL flow")
1621 var vlanID uint32
1622 if val, ok := classifierInfo[VlanVid]; ok {
1623 vlanID = (val.(uint32)) & VlanvIDMask
1624 } else {
1625 vlanID = DefaultMgmtVlan
1626 }
1627 if pcp, ok := classifierInfo[VlanPcp]; ok {
1628 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1629 tp_pb.Direction_UPSTREAM,
1630 pcp.(uint32))
1631
1632 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID[0], gemPort, vlanID)
1633 } else {
1634 installFlowOnAllGemports(nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, EapolFlow, vlanID)
1635 }
1636 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001637 } else if _, ok := actionInfo[PushVlan]; ok {
1638 log.Info("Adding upstream data rule")
1639 if pcp, ok := classifierInfo[VlanPcp]; ok {
1640 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1641 tp_pb.Direction_UPSTREAM,
1642 pcp.(uint32))
1643 //Adding HSIA upstream flow
1644 f.addUpstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
1645 } else {
1646 //Adding HSIA upstream flow to all gemports
1647 installFlowOnAllGemports(f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1648 }
1649 } else if _, ok := actionInfo[PopVlan]; ok {
1650 log.Info("Adding Downstream data rule")
1651 if pcp, ok := classifierInfo[VlanPcp]; ok {
1652 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05001653 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001654 pcp.(uint32))
1655 //Adding HSIA downstream flow
1656 f.addDownstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
1657 } else {
1658 //Adding HSIA downstream flow to all gemports
1659 installFlowOnAllGemports(f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1660 }
1661 } else {
1662 log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
1663 return
1664 }
1665 // Send Techprofile download event to child device in go routine as it takes time
1666 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, TpID)
1667}
1668
1669func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07001670 for _, field := range flows.GetOfbFields(flow) {
1671 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001672 classifierInfo[EthType] = field.GetEthType()
1673 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001674 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001675 classifierInfo[IPProto] = field.GetIpProto()
1676 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001677 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001678 classifierInfo[InPort] = field.GetPort()
1679 log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001680 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05301681 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
salmansiddiqui7ac62132019-08-22 03:58:50 +00001682 log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001683 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001684 classifierInfo[VlanPcp] = field.GetVlanPcp()
1685 log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001686 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001687 classifierInfo[UDPDst] = field.GetUdpDst()
1688 log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001689 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001690 classifierInfo[UDPSrc] = field.GetUdpSrc()
1691 log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001692 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001693 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
1694 log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001695 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001696 classifierInfo[Ipv4Src] = field.GetIpv4Src()
1697 log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001698 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001699 classifierInfo[Metadata] = field.GetTableMetadata()
1700 log.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07001701 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001702 classifierInfo[TunnelID] = field.GetTunnelId()
1703 log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
1704 } else {
1705 log.Errorw("Un supported field type", log.Fields{"type": field.Type})
1706 return
1707 }
1708 }
1709}
1710
1711func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07001712 for _, action := range flows.GetActions(flow) {
1713 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001714 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001715 actionInfo[Output] = out.GetPort()
1716 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001717 } else {
1718 log.Error("Invalid output port in action")
1719 return errors.New("invalid output port in action")
1720 }
Scott Baker355d1742019-10-24 10:57:52 -07001721 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001722 actionInfo[PopVlan] = true
1723 log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001724 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001725 if out := action.GetPush(); out != nil {
1726 if tpid := out.GetEthertype(); tpid != 0x8100 {
1727 log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
1728 } else {
1729 actionInfo[PushVlan] = true
1730 actionInfo[TPID] = tpid
1731 log.Debugw("action-type-push-vlan",
1732 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
1733 }
1734 }
Scott Baker355d1742019-10-24 10:57:52 -07001735 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001736 if out := action.GetSetField(); out != nil {
1737 if field := out.GetField(); field != nil {
1738 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
1739 log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
1740 return errors.New("invalid openflow class")
1741 }
1742 /*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
1743 if ofbField := field.GetOfbField(); ofbField != nil {
1744 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
1745 if vlan := ofbField.GetVlanVid(); vlan != 0 {
1746 actionInfo[VlanVid] = vlan & 0xfff
1747 log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
1748 } else {
1749 log.Error("No Invalid vlan id in set vlan-vid action")
1750 }
1751 } else {
1752 log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
1753 }
1754 }
1755 }
1756 }
1757 } else {
1758 log.Errorw("Un supported action type", log.Fields{"type": action.Type})
1759 return errors.New("un supported action type")
1760 }
1761 }
1762 return nil
1763}
1764
1765func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001766 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001767 log.Debug("Controller bound trap flows, getting inport from tunnelid")
1768 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
1769 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001770 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001771 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07001772 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 +00001773 } else {
1774 log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1775 return errors.New("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1776 }
1777 }
1778 } else {
1779 log.Debug("Non-Controller flows, getting uniport from tunnelid")
1780 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07001781 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001782 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001783 actionInfo[Output] = uniPort
1784 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 +00001785 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001786 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 +00001787 return errors.New("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid")
1788 }
1789 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
1790 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001791 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001792 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07001793 log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[Output].(uint32),
1794 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001795 } else {
1796 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 -07001797 "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001798 return errors.New("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid")
1799 }
1800 }
1801 }
1802 return nil
1803}