blob: 900f442b9ad981469d053c1f086a7aa058dab331 [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
Girish Gowdra26f344b2019-10-23 14:39:13 +0530554 dlClVid, ok := downlinkClassifier[VlanVid].(int)
555 if ok {
556 downlinkAction[VlanVid] = dlClVid & 0xfff
557 } else {
558 log.Error("dl-classifier-vid-type-conversion-failed")
559 return
560 }
561
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700562 f.addHSIAFlow(intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700563 Downstream, logicalFlow, allocID, gemportID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530564}
565
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700566func (f *OpenOltFlowMgr) addHSIAFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +0530567 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700568 allocID uint32, gemPortID uint32) {
Manikkaraj k884c1242019-04-11 16:26:42 +0530569 /* One of the OLT platform (Broadcom BAL) requires that symmetric
570 flows require the same flow_id to be used across UL and DL.
571 Since HSIA flow is the only symmetric flow currently, we need to
572 re-use the flow_id across both direction. The 'flow_category'
573 takes priority over flow_cookie to find any available HSIA_FLOW
574 id for the ONU.
575 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700576 log.Debugw("Adding HSIA flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "classifier": classifier,
577 "action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530578 "logicalFlow": *logicalFlow})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000579 var vlanPit uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400580 if _, ok := classifier[VlanPcp]; ok {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000581 vlanPit = classifier[VlanPcp].(uint32)
582 log.Debugw("Found pbit in the flow", log.Fields{"vlan_pit": vlanPit})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400583 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700584 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000585 flowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, HsiaFlow, vlanPit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530586 if err != nil {
587 log.Errorw("Flow id unavailable for HSIA flow", log.Fields{"direction": direction})
588 return
589 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700590 var classifierProto *openoltpb2.Classifier
591 var actionProto *openoltpb2.Action
Manikkaraj k884c1242019-04-11 16:26:42 +0530592 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
593 log.Error("Error in making classifier protobuf for hsia flow")
594 return
595 }
596 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
597 if actionProto = makeOpenOltActionField(action); actionProto == nil {
598 log.Errorw("Error in making action protobuf for hsia flow", log.Fields{"direction": direction})
599 return
600 }
601 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700602 networkIntfID := f.deviceHandler.nniIntfID
603 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
604 OnuId: int32(onuID),
605 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000606 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530607 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700608 AllocId: int32(allocID),
609 NetworkIntfId: int32(networkIntfID),
610 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530611 Classifier: classifierProto,
612 Action: actionProto,
613 Priority: int32(logicalFlow.Priority),
614 Cookie: logicalFlow.Cookie,
615 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400616 if ok := f.addFlowToDevice(logicalFlow, &flow); ok {
Manikkaraj k884c1242019-04-11 16:26:42 +0530617 log.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000618 flowsToKVStore := f.getUpdatedFlowInfo(&flow, flowStoreCookie, HsiaFlow, flowID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530619 if err := f.updateFlowInfoToKVStore(flow.AccessIntfId,
620 flow.OnuId,
621 flow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400622 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530623 log.Errorw("Error uploading HSIA flow into KV store", log.Fields{"flow": flow, "direction": direction, "error": err})
624 return
625 }
626 }
627}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700628func (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 +0530629
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700630 var dhcpFlow openoltpb2.Flow
631 var actionProto *openoltpb2.Action
632 var classifierProto *openoltpb2.Classifier
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530633
634 // Clear the action map
635 for k := range action {
636 delete(action, k)
637 }
638
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700639 action[TrapToHost] = true
640 classifier[UDPSrc] = uint32(68)
641 classifier[UDPDst] = uint32(67)
642 classifier[PacketTagType] = SingleTag
643 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530644
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700645 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530646
Manikkaraj kb1d51442019-07-23 10:41:02 -0400647 flowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, "", 0 /*classifier[VLAN_PCP].(uint32)*/)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530648
649 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700650 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530651 return
652 }
653
654 log.Debugw("Creating UL DHCP flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID})
655
656 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
657 log.Error("Error in making classifier protobuf for ul flow")
658 return
659 }
660 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
661 if actionProto = makeOpenOltActionField(action); actionProto == nil {
662 log.Error("Error in making action protobuf for ul flow")
663 return
664 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700665 networkIntfID := f.deviceHandler.nniIntfID
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530666
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700667 dhcpFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
668 OnuId: int32(onuID),
669 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530670 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700671 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700672 AllocId: int32(allocID),
673 NetworkIntfId: int32(networkIntfID),
674 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530675 Classifier: classifierProto,
676 Action: actionProto,
677 Priority: int32(logicalFlow.Priority),
678 Cookie: logicalFlow.Cookie,
679 PortNo: portNo}
680
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400681 if ok := f.addFlowToDevice(logicalFlow, &dhcpFlow); ok {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530682 log.Debug("DHCP UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400683 flowsToKVStore := f.getUpdatedFlowInfo(&dhcpFlow, flowStoreCookie, "DHCP", flowID)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530684 if err := f.updateFlowInfoToKVStore(dhcpFlow.AccessIntfId,
685 dhcpFlow.OnuId,
686 dhcpFlow.UniId,
687 dhcpFlow.FlowId, flowsToKVStore); err != nil {
688 log.Errorw("Error uploading DHCP UL flow into KV store", log.Fields{"flow": dhcpFlow, "error": err})
689 return
690 }
691 }
692
manikkaraj kbf256be2019-03-25 00:13:48 +0530693 return
694}
695
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700696// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
697func (f *OpenOltFlowMgr) addEAPOLFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, vlanID uint32) {
698 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 +0530699
700 uplinkClassifier := make(map[string]interface{})
701 uplinkAction := make(map[string]interface{})
702 downlinkClassifier := make(map[string]interface{})
703 downlinkAction := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700704 var upstreamFlow openoltpb2.Flow
705 var downstreamFlow openoltpb2.Flow
manikkaraj kbf256be2019-03-25 00:13:48 +0530706
707 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700708 uplinkClassifier[EthType] = uint32(EapEthType)
709 uplinkClassifier[PacketTagType] = SingleTag
710 uplinkClassifier[VlanVid] = vlanID
manikkaraj kbf256be2019-03-25 00:13:48 +0530711 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700712 uplinkAction[TrapToHost] = true
713 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530714 //Add Uplink EAPOL Flow
Manikkaraj kb1d51442019-07-23 10:41:02 -0400715 uplinkFlowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530716 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700717 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manikkaraj k884c1242019-04-11 16:26:42 +0530718 return
manikkaraj kbf256be2019-03-25 00:13:48 +0530719 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700720 var classifierProto *openoltpb2.Classifier
721 var actionProto *openoltpb2.Action
722 log.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530723
724 if classifierProto = makeOpenOltClassifierField(uplinkClassifier); classifierProto == nil {
725 log.Error("Error in making classifier protobuf for ul flow")
726 return
727 }
728 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
729 if actionProto = makeOpenOltActionField(uplinkAction); actionProto == nil {
730 log.Error("Error in making action protobuf for ul flow")
731 return
732 }
733 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700734 networkIntfID := f.deviceHandler.nniIntfID
735 upstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
736 OnuId: int32(onuID),
737 UniId: int32(uniID),
738 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700739 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700740 AllocId: int32(allocID),
741 NetworkIntfId: int32(networkIntfID),
742 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530743 Classifier: classifierProto,
744 Action: actionProto,
745 Priority: int32(logicalFlow.Priority),
746 Cookie: logicalFlow.Cookie,
747 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400748 if ok := f.addFlowToDevice(logicalFlow, &upstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530749 log.Debug("EAPOL UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400750 flowCategory := "EAPOL"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700751 flowsToKVStore := f.getUpdatedFlowInfo(&upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530752 if err := f.updateFlowInfoToKVStore(upstreamFlow.AccessIntfId,
753 upstreamFlow.OnuId,
754 upstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400755 upstreamFlow.FlowId,
756 /* lowCategory, */
757 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530758 log.Errorw("Error uploading EAPOL UL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
759 return
760 }
761 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400762 // Dummy Downstream flow due to BAL 2.6 limitation
763 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530764 /* Add Downstream EAPOL Flow, Only for first EAP flow (BAL
765 # requirement)
766 # On one of the platforms (Broadcom BAL), when same DL classifier
767 # vlan was used across multiple ONUs, eapol flow re-adds after
768 # flow delete (cases of onu reboot/disable) fails.
769 # In order to generate unique vlan, a combination of intf_id
770 # onu_id and uniId is used.
771 # uniId defaults to 0, so add 1 to it.
772 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700773 log.Debugw("Creating DL EAPOL flow with default vlan", log.Fields{"vlan": vlanID})
774 specialVlanDlFlow := 4090 - intfID*onuID*(uniID+1)
manikkaraj kbf256be2019-03-25 00:13:48 +0530775 // Assert that we do not generate invalid vlans under no condition
776 if specialVlanDlFlow <= 2 {
777 log.Fatalw("invalid-vlan-generated", log.Fields{"vlan": specialVlanDlFlow})
778 return
779 }
780 log.Debugw("specialVlanEAPOLDlFlow:", log.Fields{"dl_vlan": specialVlanDlFlow})
781 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700782 downlinkClassifier[PacketTagType] = SingleTag
Manikkaraj kb1d51442019-07-23 10:41:02 -0400783 downlinkClassifier[EthType] = uint32(EapEthType)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700784 downlinkClassifier[VlanVid] = uint32(specialVlanDlFlow)
manikkaraj kbf256be2019-03-25 00:13:48 +0530785 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700786 downlinkAction[PushVlan] = true
787 downlinkAction[VlanVid] = vlanID
788 flowStoreCookie := getFlowStoreCookie(downlinkClassifier, gemPortID)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000789 downlinkFlowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530790 if err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530791 log.Errorw("flowId unavailable for DL EAPOL",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700792 log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
manikkaraj kbf256be2019-03-25 00:13:48 +0530793 return
794 }
795 log.Debugw("Creating DL EAPOL flow",
salmansiddiqui7ac62132019-08-22 03:58:50 +0000796 log.Fields{"dl_classifier": downlinkClassifier, "dl_action": downlinkAction, "downlinkFlowID": downlinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530797 if classifierProto = makeOpenOltClassifierField(downlinkClassifier); classifierProto == nil {
798 log.Error("Error in making classifier protobuf for downlink flow")
799 return
800 }
801 if actionProto = makeOpenOltActionField(downlinkAction); actionProto == nil {
802 log.Error("Error in making action protobuf for dl flow")
803 return
804 }
805 // Downstream flow in grpc protobuf
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700806 downstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
807 OnuId: int32(onuID),
808 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000809 FlowId: downlinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700810 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700811 AllocId: int32(allocID),
812 NetworkIntfId: int32(networkIntfID),
813 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530814 Classifier: classifierProto,
815 Action: actionProto,
816 Priority: int32(logicalFlow.Priority),
817 Cookie: logicalFlow.Cookie,
818 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400819 if ok := f.addFlowToDevice(logicalFlow, &downstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530820 log.Debug("EAPOL DL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400821 flowCategory := ""
salmansiddiqui7ac62132019-08-22 03:58:50 +0000822 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamFlow, flowStoreCookie, flowCategory, downlinkFlowID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530823 if err := f.updateFlowInfoToKVStore(downstreamFlow.AccessIntfId,
824 downstreamFlow.OnuId,
825 downstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400826 downstreamFlow.FlowId,
827 /* flowCategory, */
828 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530829 log.Errorw("Error uploading EAPOL DL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
830 return
831 }
832 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530833 }
834 log.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
835}
836
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700837func makeOpenOltClassifierField(classifierInfo map[string]interface{}) *openoltpb2.Classifier {
838 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -0700839
840 classifier.EthType, _ = classifierInfo[EthType].(uint32)
841 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
842 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
843 vid := vlanID & VlanvIDMask
844 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -0400845 classifier.OVid = vid
846 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530847 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700848 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
849 vid := uint32(metadata)
850 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -0400851 classifier.IVid = vid
852 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530853 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700854 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400855 if vlanPcp == 0 {
856 classifier.OPbits = VlanPCPMask
857 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700858 classifier.OPbits = vlanPcp & VlanPCPMask
Manikkaraj kb1d51442019-07-23 10:41:02 -0400859 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530860 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700861 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
862 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
863 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
864 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
865 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
866 classifier.PktTagType = pktTagType
867
868 switch pktTagType {
869 case SingleTag:
870 case DoubleTag:
871 case Untagged:
872 default:
manikkaraj kbf256be2019-03-25 00:13:48 +0530873 log.Error("Invalid tag type in classifier") // should not hit
874 return nil
875 }
876 }
877 return &classifier
878}
879
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700880func makeOpenOltActionField(actionInfo map[string]interface{}) *openoltpb2.Action {
881 var actionCmd openoltpb2.ActionCmd
882 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +0530883 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700884 if _, ok := actionInfo[PopVlan]; ok {
885 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530886 action.Cmd.RemoveOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700887 } else if _, ok := actionInfo[PushVlan]; ok {
888 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530889 action.Cmd.AddOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700890 } else if _, ok := actionInfo[TrapToHost]; ok {
891 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +0530892 } else {
893 log.Errorw("Invalid-action-field", log.Fields{"action": actionInfo})
894 return nil
895 }
896 return &action
897}
898
Manikkaraj kb1d51442019-07-23 10:41:02 -0400899func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uni string, TpID uint32) string {
900 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530901}
902
Devmalya Paul495b94a2019-08-27 19:42:00 -0400903// DeleteTechProfileInstance removes the tech profile instance from persistent storage
904func (f *OpenOltFlowMgr) DeleteTechProfileInstance(intfID uint32, onuID uint32, uniID uint32, sn string) error {
905 tpID := f.resourceMgr.GetTechProfileIDForOnu(intfID, onuID, uniID)
906 uniPortName := fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
907 if err := f.techprofile[intfID].DeleteTechProfileInstance(tpID, uniPortName); err != nil {
908 log.Debugw("Failed-to-delete-tp-instance-from-kv-store", log.Fields{"tp-id": tpID, "uni-port-name": uniPortName})
909 return err
910 }
911 return nil
912}
913
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700914func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530915 if len(classifier) == 0 { // should never happen
916 log.Error("Invalid classfier object")
917 return 0
918 }
919 var jsonData []byte
920 var flowString string
921 var err error
922 // TODO: Do we need to marshall ??
923 if jsonData, err = json.Marshal(classifier); err != nil {
924 log.Error("Failed to encode classifier")
925 return 0
926 }
927 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700928 if gemPortID != 0 {
929 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +0530930 }
931 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700932 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +0530933 hash := big.NewInt(0)
934 hash.SetBytes(h.Sum(nil))
935 return hash.Uint64()
936}
937
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700938func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openoltpb2.Flow, flowStoreCookie uint64, flowCategory string, deviceFlowID uint32) *[]rsrcMgr.FlowInfo {
939 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
940 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400941 /* For flows which trap out of the NNI, the AccessIntfId is invalid
942 (set to -1). In such cases, we need to refer to the NetworkIntfId .
943 */
944 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700945 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400946 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700947 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400948 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700949 // Get existing flows matching flowid for given subscriber from KV store
950 existingFlows := f.resourceMgr.GetFlowIDInfo(intfID, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -0400951 if existingFlows != nil {
952 log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700953 //for _, f := range *existingFlows {
954 // flows = append(flows, f)
955 //}
956 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -0400957 }
958 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 +0530959 return &flows
960}
961
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400962//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
963// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
964// var intfId uint32
965// /* For flows which trap out of the NNI, the AccessIntfId is invalid
966// (set to -1). In such cases, we need to refer to the NetworkIntfId .
967// */
968// if flow.AccessIntfId != -1 {
969// intfId = uint32(flow.AccessIntfId)
970// } else {
971// intfId = uint32(flow.NetworkIntfId)
972// }
973// // Get existing flows matching flowid for given subscriber from KV store
974// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
975// if existingFlows != nil {
976// log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
977// for _, f := range *existingFlows {
978// flows = append(flows, f)
979// }
980// }
981// log.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
982// return &flows
983//}
984
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700985func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
manikkaraj k17652a72019-05-06 09:06:36 -0400986 log.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700987 if err := f.resourceMgr.UpdateFlowIDInfo(intfID, onuID, uniID, flowID, flows); err != nil {
manikkaraj k17652a72019-05-06 09:06:36 -0400988 log.Debug("Error while Storing flow into KV store")
989 return err
990 }
991 log.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +0530992 return nil
993}
994
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700995func (f *OpenOltFlowMgr) addFlowToDevice(logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) bool {
Daniele Rossi22db98e2019-07-11 11:50:00 +0000996
997 var intfID uint32
998 /* For flows which trap out of the NNI, the AccessIntfId is invalid
999 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1000 */
1001 if deviceFlow.AccessIntfId != -1 {
1002 intfID = uint32(deviceFlow.AccessIntfId)
1003 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001004 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001005 intfID = uint32(deviceFlow.NetworkIntfId)
1006 }
1007
manikkaraj kbf256be2019-03-25 00:13:48 +05301008 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1009 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001010
1011 st, _ := status.FromError(err)
1012 if st.Code() == codes.AlreadyExists {
1013 log.Debug("Flow already exixts", log.Fields{"err": err, "deviceFlow": deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301014 return false
1015 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001016
1017 if err != nil {
1018 log.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": deviceFlow})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001019 f.resourceMgr.FreeFlowID(intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001020 return false
1021 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001022 log.Debugw("Flow added to device successfully ", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001023 f.registerFlow(logicalFlow, deviceFlow)
1024 return true
1025}
1026
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001027func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) bool {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001028 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1029 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1030 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001031 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
1032 log.Warnw("Can not remove flow from device since it's unreachable", log.Fields{"err": err, "deviceFlow": deviceFlow})
1033 //Assume the flow is removed
1034 return true
1035 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001036 log.Errorw("Failed to Remove flow from device", log.Fields{"err": err, "deviceFlow": deviceFlow})
1037 return false
serkant.uluderya245caba2019-09-24 23:15:29 -07001038
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001039 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001040 log.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301041 return true
1042}
1043
1044/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1045 //update core flows_proxy : flows_proxy.update('/', flows)
1046}
1047
1048func generateStoredId(flowId uint32, direction string)uint32{
1049
David K. Bainbridge82efc492019-09-04 09:57:11 -07001050 if direction == Upstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301051 log.Debug("Upstream flow shifting flowid")
1052 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001053 }else if direction == Downstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301054 log.Debug("Downstream flow not shifting flowid")
1055 return flowId
1056 }else{
1057 log.Errorw("Unrecognized direction",log.Fields{"direction": direction})
1058 return flowId
1059 }
1060}
1061
1062*/
1063
Humera Kouser94d7a842019-08-25 19:04:32 -04001064func (f *OpenOltFlowMgr) addLLDPFlow(flow *ofp.OfpFlowStats, portNo uint32) {
1065
1066 classifierInfo := make(map[string]interface{})
1067 actionInfo := make(map[string]interface{})
1068
1069 classifierInfo[EthType] = uint32(LldpEthType)
1070 classifierInfo[PacketTagType] = Untagged
1071 actionInfo[TrapToHost] = true
1072
1073 // LLDP flow is installed to trap LLDP packets on the NNI port.
1074 // We manage flow_id resource pool on per PON port basis.
1075 // Since this situation is tricky, as a hack, we pass the NNI port
1076 // index (network_intf_id) as PON port Index for the flow_id resource
1077 // pool. Also, there is no ONU Id available for trapping LLDP packets
1078 // on NNI port, use onu_id as -1 (invalid)
1079 // ****************** CAVEAT *******************
1080 // This logic works if the NNI Port Id falls within the same valid
1081 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1082 // we need to have a re-look at this.
1083 // *********************************************
1084
1085 var onuID = -1
1086 var uniID = -1
1087 var gemPortID = -1
1088
1089 var networkInterfaceID = IntfIDFromNniPortNum(portNo)
1090 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
1091 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), flowStoreCookie); present {
1092 log.Debug("Flow-exists--not-re-adding")
1093 return
1094 }
1095 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
1096
1097 if err != nil {
1098 log.Errorw("Flow id unavailable for LLDP traponNNI flow", log.Fields{"error": err})
1099 return
1100 }
1101 var classifierProto *openoltpb2.Classifier
1102 var actionProto *openoltpb2.Action
1103 if classifierProto = makeOpenOltClassifierField(classifierInfo); classifierProto == nil {
1104 log.Error("Error in making classifier protobuf for LLDP trap on nni flow")
1105 return
1106 }
1107 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1108 if actionProto = makeOpenOltActionField(actionInfo); actionProto == nil {
1109 log.Error("Error in making action protobuf for LLDP trap on nni flow")
1110 return
1111 }
1112 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
1113
1114 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1115 OnuId: int32(onuID), // OnuId not required
1116 UniId: int32(uniID), // UniId not used
1117 FlowId: flowID,
1118 FlowType: Downstream,
1119 NetworkIntfId: int32(networkInterfaceID),
1120 GemportId: int32(gemPortID),
1121 Classifier: classifierProto,
1122 Action: actionProto,
1123 Priority: int32(flow.Priority),
1124 Cookie: flow.Cookie,
1125 PortNo: portNo}
1126 if ok := f.addFlowToDevice(flow, &downstreamflow); ok {
1127 log.Debug("LLDP trap on NNI flow added to device successfully")
1128 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID)
1129 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1130 int32(onuID),
1131 int32(uniID),
1132 flowID, flowsToKVStore); err != nil {
1133 log.Errorw("Error uploading LLDP flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1134 }
1135 }
1136 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301137}
1138
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001139func getUniPortPath(intfID uint32, onuID uint32, uniID uint32) string {
1140 return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1141}
1142
1143//getOnuChildDevice to fetch onu
1144func (f *OpenOltFlowMgr) getOnuChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
1145 log.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
1146 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
1147 onuDevice := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301148 if onuDevice == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001149 log.Errorw("onu not found", log.Fields{"intfId": parentPortNo, "onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301150 return nil, errors.New("onu not found")
manikkaraj kbf256be2019-03-25 00:13:48 +05301151 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301152 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1153 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301154}
1155
1156func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001157 log.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301158 return nil
1159}
1160
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001161func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
1162 log.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301163}
1164
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001165func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001166 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001167 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001168 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001169 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001170}
1171
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001172func (f *OpenOltFlowMgr) clearFlowFromResourceManager(flow *ofp.OfpFlowStats, flowID uint32, flowDirection string) {
1173 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowID": flowID, "flowDirection": flowDirection, "flow": *flow})
Humera Kouser94d7a842019-08-25 19:04:32 -04001174 portNum, ponIntf, onuID, uniID, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001175 if err != nil {
1176 log.Error(err)
1177 return
1178 }
1179 log.Debugw("Extracted access info from flow to be deleted",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001180 log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001181
Humera Kouser94d7a842019-08-25 19:04:32 -04001182 if ethType == LldpEthType {
1183 var networkInterfaceID uint32
1184 var onuID = -1
1185 var uniID = -1
1186
1187 networkInterfaceID = IntfIDFromNniPortNum(inPort)
1188 f.resourceMgr.FreeFlowID(networkInterfaceID, int32(onuID), int32(uniID), flowID)
1189 return
1190 }
1191
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001192 flowsInfo := f.resourceMgr.GetFlowIDInfo(ponIntf, onuID, uniID, flowID)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001193 if flowsInfo == nil {
1194 log.Debugw("No FlowInfo found found in KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001195 log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001196 return
1197 }
1198 var updatedFlows []rsrcMgr.FlowInfo
1199
1200 for _, flow := range *flowsInfo {
1201 updatedFlows = append(updatedFlows, flow)
1202 }
1203
1204 for i, storedFlow := range updatedFlows {
1205 if flowDirection == storedFlow.Flow.FlowType {
1206 //Remove the Flow from FlowInfo
1207 log.Debugw("Removing flow to be deleted", log.Fields{"flow": storedFlow})
1208 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1209 break
1210 }
1211 }
1212
1213 if len(updatedFlows) >= 0 {
1214 // There are still flows referencing the same flow_id.
1215 // So the flow should not be freed yet.
1216 // For ex: Case of HSIA where same flow is shared
1217 // between DS and US.
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001218 f.updateFlowInfoToKVStore(int32(ponIntf), int32(onuID), int32(uniID), flowID, &updatedFlows)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001219 if len(updatedFlows) == 0 {
1220 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 -04001221 f.resourceMgr.FreeFlowID(ponIntf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001222 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001223 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001224 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ponIntf, onuID, uniID)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001225 if len(flowIds) == 0 {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001226 log.Debugf("Flow count for subscriber %d is zero", onuID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001227 kvstoreTpID := f.resourceMgr.GetTechProfileIDForOnu(ponIntf, onuID, uniID)
1228 if kvstoreTpID == 0 {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001229 log.Warnw("Could-not-find-techprofile-tableid-for-uni", log.Fields{"ponIntf": ponIntf, "onuId": onuID, "uniId": uniID})
1230 return
1231 }
1232 uni := getUniPortPath(ponIntf, onuID, uniID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001233 tpPath := f.getTPpath(ponIntf, uni, kvstoreTpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001234 log.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001235 techprofileInst, err := f.techprofile[ponIntf].GetTPInstanceFromKVStore(kvstoreTpID, tpPath)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001236 if err != nil { // This should not happen, something wrong in KV backend transaction
1237 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": 20, "path": tpPath})
1238 return
1239 }
1240 if techprofileInst == nil {
1241 log.Errorw("Tech-profile-instance-does-not-exist-in-KV Store", log.Fields{"tpPath": tpPath})
1242 return
1243 }
1244
1245 f.RemoveSchedulerQueues(tp_pb.Direction_UPSTREAM, ponIntf, onuID, uniID, portNum, techprofileInst)
1246 f.RemoveSchedulerQueues(tp_pb.Direction_DOWNSTREAM, ponIntf, onuID, uniID, portNum, techprofileInst)
1247 } else {
1248 log.Debugf("Flow ids for subscriber", log.Fields{"onu": onuID, "flows": flowIds})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001249 }
1250}
1251
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001252//RemoveFlow removes the flow from the device
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001253func (f *OpenOltFlowMgr) RemoveFlow(flow *ofp.OfpFlowStats) {
1254 log.Debugw("Removing Flow", log.Fields{"flow": flow})
1255 var deviceFlowsToRemove []ofp.OfpFlowStats
1256 var deletedFlowsIdx []int
1257 for _, curFlow := range f.storedDeviceFlows {
1258 if curFlow.Cookie == flow.Id {
1259 log.Debugw("Found found matching flow-cookie", log.Fields{"curFlow": curFlow})
1260 deviceFlowsToRemove = append(deviceFlowsToRemove, curFlow)
1261 }
1262 }
1263 log.Debugw("Flows to be deleted", log.Fields{"deviceFlowsToRemove": deviceFlowsToRemove})
1264 for index, curFlow := range deviceFlowsToRemove {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001265 id, direction := f.decodeStoredID(curFlow.GetId())
1266 removeFlowMessage := openoltpb2.Flow{FlowId: uint32(id), FlowType: direction}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001267 if ok := f.removeFlowFromDevice(&removeFlowMessage); ok {
1268 log.Debug("Flow removed from device successfully")
1269 deletedFlowsIdx = append(deletedFlowsIdx, index)
1270 f.clearFlowFromResourceManager(flow, uint32(id), direction) //TODO: Take care of the limitations
1271 }
1272
1273 }
1274 // Can be done in separate go routine as it takes time ?
1275 for _, flowToRemove := range deletedFlowsIdx {
1276 for index, storedFlow := range f.storedDeviceFlows {
1277 if deviceFlowsToRemove[flowToRemove].Cookie == storedFlow.Cookie {
1278 log.Debugw("Removing flow from local Store", log.Fields{"flow": storedFlow})
1279 f.storedDeviceFlows = append(f.storedDeviceFlows[:index], f.storedDeviceFlows[index+1:]...)
1280 break
1281 }
1282 }
1283 }
1284 log.Debugw("Flows removed from the data store",
1285 log.Fields{"number_of_flows_removed": len(deviceFlowsToRemove), "updated_stored_flows": f.storedDeviceFlows})
1286 return
1287}
1288
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001289// AddFlow add flow to device
Manikkaraj kb1d51442019-07-23 10:41:02 -04001290func (f *OpenOltFlowMgr) AddFlow(flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001291 classifierInfo := make(map[string]interface{})
1292 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001293 var UsMeterID uint32
1294 var DsMeterID uint32
1295
1296 log.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001297 formulateClassifierInfoFromFlow(classifierInfo, flow)
1298
1299 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
1300 if err != nil {
1301 // Error logging is already done in the called function
1302 // So just return in case of error
1303 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301304 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001305
manikkaraj k17652a72019-05-06 09:06:36 -04001306 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00001307 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
1308 if err != nil {
1309 // error if any, already logged in the called function
1310 return
manikkaraj k17652a72019-05-06 09:06:36 -04001311 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001312
David K. Bainbridge82efc492019-09-04 09:57:11 -07001313 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[Output]})
1314 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00001315
Humera Kouser94d7a842019-08-25 19:04:32 -04001316 if ethType, ok := classifierInfo[EthType]; ok {
1317 if ethType.(uint32) == LldpEthType {
1318 log.Info("Adding LLDP flow")
1319 f.addLLDPFlow(flow, portNo)
1320 return
1321 }
1322 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001323 if ipProto, ok := classifierInfo[IPProto]; ok {
1324 if ipProto.(uint32) == IPProtoDhcp {
1325 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001326 if udpSrc.(uint32) == uint32(67) {
1327 log.Debug("trap-dhcp-from-nni-flow")
1328 f.addDHCPTrapFlowOnNNI(flow, classifierInfo, portNo)
1329 return
1330 }
1331 }
1332 }
1333 }
A R Karthick1f85b802019-10-11 05:06:05 +00001334
1335 f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
1336
Manikkaraj kb1d51442019-07-23 10:41:02 -04001337 /* Metadata 8 bytes:
1338 Most Significant 2 Bytes = Inner VLAN
1339 Next 2 Bytes = Tech Profile ID(TPID)
1340 Least Significant 4 Bytes = Port ID
David K. Bainbridge82efc492019-09-04 09:57:11 -07001341 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
Manikkaraj kb1d51442019-07-23 10:41:02 -04001342 subscriber related flows.
1343 */
Scott Baker355d1742019-10-24 10:57:52 -07001344 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001345 if metadata == 0 {
1346 log.Error("Metadata is not present in flow which is mandatory")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001347 return
1348 }
Scott Baker355d1742019-10-24 10:57:52 -07001349 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001350 kvstoreTpID := f.resourceMgr.GetTechProfileIDForOnu(intfID, onuID, uniID)
1351 if kvstoreTpID == 0 {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001352 log.Debugf("tpid-not-present-in-kvstore, using tp id %d from flow metadata", TpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001353 } else if kvstoreTpID != uint32(TpID) {
1354 log.Error(" Tech-profile-updates-not-supported", log.Fields{"Tpid-in-flow": TpID, "kvstore-TpId": kvstoreTpID})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001355 return
1356 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001357 log.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001358 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07001359 UsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001360 log.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
1361 } else {
Scott Baker355d1742019-10-24 10:57:52 -07001362 DsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001363 log.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
1364
1365 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001366 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001367}
1368
1369//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04001370func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001371
1372 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301373 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001374 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301375 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301376 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301377 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04001378
Manikkaraj kb1d51442019-07-23 10:41:02 -04001379 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001380 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
manikkaraj k17652a72019-05-06 09:06:36 -04001381 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
1382 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1383 tpDownloadMsg,
1384 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
1385 f.deviceHandler.deviceType,
1386 onuDevice.Type,
1387 onuDevice.Id,
1388 onuDevice.ProxyAddress.DeviceId, "")
1389 if sendErr != nil {
1390 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1391 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1392 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1393 return sendErr
1394 }
1395 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05301396 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301397}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001398
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001399//UpdateOnuInfo function adds onu info to cache
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001400func (f *OpenOltFlowMgr) UpdateOnuInfo(intfID uint32, onuID uint32, serialNum string) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001401 onu := onuInfo{intfID: intfID, onuID: onuID, serialNumber: serialNum}
1402 onuIDkey := onuIDKey{intfID: intfID, onuID: onuID}
William Kurkian740a09c2019-10-23 17:07:38 -04001403 f.onuIdsLock.Lock()
1404 defer f.onuIdsLock.Unlock()
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001405 f.onuIds[onuIDkey] = onu
1406 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
1407}
1408
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001409//addGemPortToOnuInfoMap function stores adds GEMport to ONU map
1410func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(intfID uint32, onuID uint32, gemPort uint32) {
1411 onuIDkey := onuIDKey{intfID: intfID, onuID: onuID}
William Kurkian740a09c2019-10-23 17:07:38 -04001412 f.onuIdsLock.RLock()
1413 defer f.onuIdsLock.RUnlock()
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001414 if val, ok := f.onuIds[onuIDkey]; ok {
kdarapu3248f9a2019-10-03 13:54:52 +05301415 onuInf := val
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001416 gemportKey := gemPortKey{intfID: intfID, gemPort: gemPort}
kdarapu3248f9a2019-10-03 13:54:52 +05301417 f.onuGemPortIds[gemportKey] = onuInf
1418 log.Debugw("Cached Gemport to Onuinfo map", log.Fields{"GemPort": gemPort, "intfId": onuInf.intfID, "onuId": onuInf.onuID})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001419 return
1420 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001421 log.Errorw("OnuInfo not found", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001422}
1423
1424// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001425
1426//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
1427func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
1428 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 -04001429 if serialNumber != "" {
kdarapu3248f9a2019-10-03 13:54:52 +05301430 if onuInf, ok := f.onuSerialNumbers[serialNumber]; ok {
1431 return onuInf.onuID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001432 }
1433 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001434 gemportKey := gemPortKey{intfID: intfID, gemPort: gemPortID}
kdarapu3248f9a2019-10-03 13:54:52 +05301435 if onuInf, ok := f.onuGemPortIds[gemportKey]; ok {
1436 log.Debugw("Retrieved onu info from access", log.Fields{"intfId": intfID, "gemPortId": gemPortID, "onuId": onuInf.onuID})
1437 return onuInf.onuID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001438 }
1439 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001440 log.Errorw("onuid is not found", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPort": gemPortID})
1441 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 -04001442}
1443
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001444//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
1445func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001446 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001447 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001448 var err error
1449
1450 if packetIn.IntfType == "pon" {
1451 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001452 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001453 log.Errorw("Unable to get ONU ID from GEM/PON port", log.Fields{"pon port": packetIn.IntfId, "gemport": packetIn.GemportId})
1454 return logicalPortNum, err
1455 }
1456 if packetIn.PortNo != 0 {
1457 logicalPortNum = packetIn.PortNo
1458 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001459 uniID := uint32(0) // FIXME - multi-uni support
1460 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001461 }
1462 // 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 -07001463 pktInkey := packetInInfoKey{intfID: packetIn.IntfId, onuID: onuID, logicalPort: logicalPortNum}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001464 f.packetInGemPort[pktInkey] = packetIn.GemportId
1465 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001466 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001467 }
1468 log.Debugw("Retrieved logicalport from packet-in", log.Fields{"logicalPortNum": logicalPortNum, "IntfType": packetIn.IntfType})
1469 return logicalPortNum, nil
1470}
1471
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001472//GetPacketOutGemPortID returns gemPortId
1473func (f *OpenOltFlowMgr) GetPacketOutGemPortID(intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
1474 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001475 var err error
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001476 key := packetInInfoKey{intfID: intfID, onuID: onuID, logicalPort: portNum}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001477 if val, ok := f.packetInGemPort[key]; ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001478 gemPortID = val
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001479 } else {
1480 log.Errorw("Key-Error while fetching packet-out GEM port", log.Fields{"key": key})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001481 err = errors.New("key-error while fetching packet-out GEM port")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001482 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001483 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001484}
1485
Manikkaraj kb1d51442019-07-23 10:41:02 -04001486func installFlowOnAllGemports(
1487 f1 func(intfId uint32, onuId uint32, uniId uint32,
1488 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
1489 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32),
1490 f2 func(intfId uint32, onuId uint32, uniId uint32, portNo uint32,
1491 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32),
1492 args map[string]uint32,
1493 classifier map[string]interface{}, action map[string]interface{},
1494 logicalFlow *ofp.OfpFlowStats,
1495 gemPorts []uint32,
1496 FlowType string,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001497 vlanID ...uint32) {
1498 log.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
1499 for _, gemPortID := range gemPorts {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001500 if FlowType == HsiaFlow || FlowType == DhcpFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001501 f1(args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001502 } else if FlowType == EapolFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001503 f2(args["intfId"], args["onuId"], args["uniId"], args["portNo"], logicalFlow, args["allocId"], gemPortID, vlanID[0])
Manikkaraj kb1d51442019-07-23 10:41:02 -04001504 } else {
1505 log.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
1506 return
1507 }
1508 }
1509}
1510
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001511func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
1512 log.Debug("Adding trap-dhcp-of-nni-flow")
1513 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001514 classifier[PacketTagType] = DoubleTag
1515 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001516 /* We manage flowId resource pool on per PON port basis.
1517 Since this situation is tricky, as a hack, we pass the NNI port
1518 index (network_intf_id) as PON port Index for the flowId resource
1519 pool. Also, there is no ONU Id available for trapping DHCP packets
1520 on NNI port, use onu_id as -1 (invalid)
1521 ****************** CAVEAT *******************
1522 This logic works if the NNI Port Id falls within the same valid
1523 range of PON Port Ids. If this doesn't work for some OLT Vendor
1524 we need to have a re-look at this.
1525 *********************************************
1526 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001527 onuID := -1
1528 uniID := -1
1529 gemPortID := -1
1530 allocID := -1
1531 networkInterfaceID := f.deviceHandler.nniIntfID
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001532 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001533 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), flowStoreCookie); present {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001534 log.Debug("Flow-exists--not-re-adding")
1535 return
1536 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001537 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001538 if err != nil {
1539 log.Errorw("Flow id unavailable for DHCP traponNNI flow", log.Fields{"error": err})
1540 return
1541 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001542 var classifierProto *openoltpb2.Classifier
1543 var actionProto *openoltpb2.Action
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001544 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
1545 log.Error("Error in making classifier protobuf for dhcp trap on nni flow")
1546 return
1547 }
1548 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1549 if actionProto = makeOpenOltActionField(action); actionProto == nil {
1550 log.Error("Error in making action protobuf for dhcp trap on nni flow")
1551 return
1552 }
1553 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001554 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1555 OnuId: int32(onuID), // OnuId not required
1556 UniId: int32(uniID), // UniId not used
1557 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001558 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001559 AllocId: int32(allocID), // AllocId not used
1560 NetworkIntfId: int32(networkInterfaceID),
1561 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001562 Classifier: classifierProto,
1563 Action: actionProto,
1564 Priority: int32(logicalFlow.Priority),
1565 Cookie: logicalFlow.Cookie,
1566 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001567 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001568 log.Debug("DHCP trap on NNI flow added to device successfully")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001569 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID)
1570 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1571 int32(onuID),
1572 int32(uniID),
1573 flowID, flowsToKVStore); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001574 log.Errorw("Error uploading DHCP DL flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1575 }
1576 }
1577 return
1578}
salmansiddiqui7ac62132019-08-22 03:58:50 +00001579
1580func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
1581 if MeterID == 0 { // This should never happen
1582 log.Error("Invalid meter id")
1583 return "", errors.New("invalid meter id")
1584 }
1585 if Dir == tp_pb.Direction_UPSTREAM {
1586 return "upstream", nil
1587 } else if Dir == tp_pb.Direction_DOWNSTREAM {
1588 return "downstream", nil
1589 }
1590 return "", nil
1591}
1592
1593func (f *OpenOltFlowMgr) checkAndAddFlow(args map[string]uint32, classifierInfo map[string]interface{},
1594 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, gemPort, intfID, onuID, uniID, portNo uint32,
1595 TpInst *tp.TechProfile, allocID []uint32, gemPorts []uint32, TpID uint32, uni string) {
1596 if ipProto, ok := classifierInfo[IPProto]; ok {
1597 if ipProto.(uint32) == IPProtoDhcp {
1598 log.Info("Adding DHCP flow")
1599 if pcp, ok := classifierInfo[VlanPcp]; ok {
1600 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1601 tp_pb.Direction_UPSTREAM,
1602 pcp.(uint32))
1603 //Adding DHCP upstream flow
1604 f.addDHCPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
1605 } else {
1606 //Adding DHCP upstream flow to all gemports
1607 installFlowOnAllGemports(f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, DhcpFlow)
1608 }
1609
1610 } else if ipProto == IgmpProto {
1611 log.Info("igmp flow add ignored, not implemented yet")
1612 return
1613 } else {
1614 log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
1615 return
1616 }
1617 } else if ethType, ok := classifierInfo[EthType]; ok {
1618 if ethType.(uint32) == EapEthType {
1619 log.Info("Adding EAPOL flow")
1620 var vlanID uint32
1621 if val, ok := classifierInfo[VlanVid]; ok {
1622 vlanID = (val.(uint32)) & VlanvIDMask
1623 } else {
1624 vlanID = DefaultMgmtVlan
1625 }
1626 if pcp, ok := classifierInfo[VlanPcp]; ok {
1627 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1628 tp_pb.Direction_UPSTREAM,
1629 pcp.(uint32))
1630
1631 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID[0], gemPort, vlanID)
1632 } else {
1633 installFlowOnAllGemports(nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, EapolFlow, vlanID)
1634 }
1635 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001636 } else if _, ok := actionInfo[PushVlan]; ok {
1637 log.Info("Adding upstream data rule")
1638 if pcp, ok := classifierInfo[VlanPcp]; ok {
1639 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1640 tp_pb.Direction_UPSTREAM,
1641 pcp.(uint32))
1642 //Adding HSIA upstream flow
1643 f.addUpstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
1644 } else {
1645 //Adding HSIA upstream flow to all gemports
1646 installFlowOnAllGemports(f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1647 }
1648 } else if _, ok := actionInfo[PopVlan]; ok {
1649 log.Info("Adding Downstream data rule")
1650 if pcp, ok := classifierInfo[VlanPcp]; ok {
1651 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05001652 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001653 pcp.(uint32))
1654 //Adding HSIA downstream flow
1655 f.addDownstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID[0], gemPort)
1656 } else {
1657 //Adding HSIA downstream flow to all gemports
1658 installFlowOnAllGemports(f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1659 }
1660 } else {
1661 log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
1662 return
1663 }
1664 // Send Techprofile download event to child device in go routine as it takes time
1665 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, TpID)
1666}
1667
1668func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07001669 for _, field := range flows.GetOfbFields(flow) {
1670 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001671 classifierInfo[EthType] = field.GetEthType()
1672 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001673 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001674 classifierInfo[IPProto] = field.GetIpProto()
1675 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001676 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001677 classifierInfo[InPort] = field.GetPort()
1678 log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001679 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05301680 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
salmansiddiqui7ac62132019-08-22 03:58:50 +00001681 log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001682 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001683 classifierInfo[VlanPcp] = field.GetVlanPcp()
1684 log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001685 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001686 classifierInfo[UDPDst] = field.GetUdpDst()
1687 log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001688 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001689 classifierInfo[UDPSrc] = field.GetUdpSrc()
1690 log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001691 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001692 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
1693 log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001694 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001695 classifierInfo[Ipv4Src] = field.GetIpv4Src()
1696 log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001697 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001698 classifierInfo[Metadata] = field.GetTableMetadata()
1699 log.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07001700 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001701 classifierInfo[TunnelID] = field.GetTunnelId()
1702 log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
1703 } else {
1704 log.Errorw("Un supported field type", log.Fields{"type": field.Type})
1705 return
1706 }
1707 }
1708}
1709
1710func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07001711 for _, action := range flows.GetActions(flow) {
1712 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001713 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001714 actionInfo[Output] = out.GetPort()
1715 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001716 } else {
1717 log.Error("Invalid output port in action")
1718 return errors.New("invalid output port in action")
1719 }
Scott Baker355d1742019-10-24 10:57:52 -07001720 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001721 actionInfo[PopVlan] = true
1722 log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001723 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001724 if out := action.GetPush(); out != nil {
1725 if tpid := out.GetEthertype(); tpid != 0x8100 {
1726 log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
1727 } else {
1728 actionInfo[PushVlan] = true
1729 actionInfo[TPID] = tpid
1730 log.Debugw("action-type-push-vlan",
1731 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
1732 }
1733 }
Scott Baker355d1742019-10-24 10:57:52 -07001734 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001735 if out := action.GetSetField(); out != nil {
1736 if field := out.GetField(); field != nil {
1737 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
1738 log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
1739 return errors.New("invalid openflow class")
1740 }
1741 /*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
1742 if ofbField := field.GetOfbField(); ofbField != nil {
1743 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
1744 if vlan := ofbField.GetVlanVid(); vlan != 0 {
1745 actionInfo[VlanVid] = vlan & 0xfff
1746 log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
1747 } else {
1748 log.Error("No Invalid vlan id in set vlan-vid action")
1749 }
1750 } else {
1751 log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
1752 }
1753 }
1754 }
1755 }
1756 } else {
1757 log.Errorw("Un supported action type", log.Fields{"type": action.Type})
1758 return errors.New("un supported action type")
1759 }
1760 }
1761 return nil
1762}
1763
1764func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001765 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001766 log.Debug("Controller bound trap flows, getting inport from tunnelid")
1767 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
1768 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001769 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001770 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07001771 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 +00001772 } else {
1773 log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1774 return errors.New("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1775 }
1776 }
1777 } else {
1778 log.Debug("Non-Controller flows, getting uniport from tunnelid")
1779 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07001780 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001781 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001782 actionInfo[Output] = uniPort
1783 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 +00001784 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001785 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 +00001786 return errors.New("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid")
1787 }
1788 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
1789 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001790 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001791 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07001792 log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[Output].(uint32),
1793 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001794 } else {
1795 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 -07001796 "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001797 return errors.New("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid")
1798 }
1799 }
1800 }
1801 return nil
1802}