blob: f0e81f68c263fac6bc87d754809666036dd6bf1a [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
Gamze Abakafee36392019-10-03 11:17:24 +0000139 //IntfID constant
140 IntfID = "intfId"
141 //OnuID constant
142 OnuID = "onuId"
143 //UniID constant
144 UniID = "uniId"
145 //PortNo constant
146 PortNo = "portNo"
147 //AllocID constant
148 AllocID = "allocId"
manikkaraj kbf256be2019-03-25 00:13:48 +0530149)
150
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400151type onuInfo struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700152 intfID uint32
153 onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400154 serialNumber string
155}
156
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700157type onuIDKey struct {
158 intfID uint32
159 onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400160}
161
162type gemPortKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700163 intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400164 gemPort uint32
165}
166
167type packetInInfoKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700168 intfID uint32
169 onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400170 logicalPort uint32
171}
172
Gamze Abakafee36392019-10-03 11:17:24 +0000173type schedQueue struct {
174 direction tp_pb.Direction
175 intfID uint32
176 onuID uint32
177 uniID uint32
178 tpID uint32
179 uniPort uint32
180 tpInst *tp.TechProfile
181 meterID uint32
182 flowMetadata *voltha.FlowMetadata
183}
184
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700185//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530186type OpenOltFlowMgr struct {
Gamze Abakafee36392019-10-03 11:17:24 +0000187 techprofile []tp.TechProfileIf
188 deviceHandler *DeviceHandler
189 resourceMgr *rsrcMgr.OpenOltResourceMgr
190 onuIds map[onuIDKey]onuInfo //OnuId -> OnuInfo
191 onuSerialNumbers map[string]onuInfo //onu serial_number (string) -> OnuInfo
192 onuGemPortIds map[gemPortKey]onuInfo //GemPortId -> OnuInfo
193 packetInGemPort map[packetInInfoKey]uint32 //packet in gem port
194 storedDeviceFlows []ofp.OfpFlowStats /* Required during deletion to obtain device flows from logical flows */
195 onuIdsLock sync.RWMutex
196 flowsUsedByGemPort map[gemPortKey][]uint32 //gem port id to flow ids
manikkaraj kbf256be2019-03-25 00:13:48 +0530197}
198
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700199//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
manikkaraj kbf256be2019-03-25 00:13:48 +0530200func NewFlowManager(dh *DeviceHandler, rsrcMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
201 log.Info("Initializing flow manager")
202 var flowMgr OpenOltFlowMgr
203 flowMgr.deviceHandler = dh
204 flowMgr.resourceMgr = rsrcMgr
kdarapub26b4502019-10-05 03:02:33 +0530205 flowMgr.techprofile = make([]tp.TechProfileIf, MaxPonPorts)
manikkaraj kbf256be2019-03-25 00:13:48 +0530206 if err := flowMgr.populateTechProfilePerPonPort(); err != nil {
207 log.Error("Error while populating tech profile mgr\n")
208 return nil
209 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700210 flowMgr.onuIds = make(map[onuIDKey]onuInfo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400211 flowMgr.onuSerialNumbers = make(map[string]onuInfo)
212 flowMgr.onuGemPortIds = make(map[gemPortKey]onuInfo)
213 flowMgr.packetInGemPort = make(map[packetInInfoKey]uint32)
Gamze Abakafee36392019-10-03 11:17:24 +0000214 flowMgr.flowsUsedByGemPort = make(map[gemPortKey][]uint32)
William Kurkian740a09c2019-10-23 17:07:38 -0400215 flowMgr.onuIdsLock = sync.RWMutex{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530216 log.Info("Initialization of flow manager success!!")
217 return &flowMgr
218}
219
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700220func (f *OpenOltFlowMgr) generateStoredFlowID(flowID uint32, direction string) (uint64, error) {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700221 if direction == Upstream {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400222 log.Debug("upstream flow, shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700223 return 0x1<<15 | uint64(flowID), nil
David K. Bainbridge82efc492019-09-04 09:57:11 -0700224 } else if direction == Downstream {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400225 log.Debug("downstream flow, not shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700226 return uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400227 } else {
228 log.Debug("Unrecognized direction")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700229 return 0, fmt.Errorf("unrecognized direction %s", direction)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400230 }
231}
232
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700233func (f *OpenOltFlowMgr) registerFlow(flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400234 log.Debug("Registering Flow for Device ", log.Fields{"flow": flowFromCore},
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700235 log.Fields{"device": f.deviceHandler.deviceID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400236
237 var storedFlow ofp.OfpFlowStats
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700238 storedFlow.Id, _ = f.generateStoredFlowID(deviceFlow.FlowId, deviceFlow.FlowType)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400239 log.Debug(fmt.Sprintf("Generated stored device flow. id = %d, flowId = %d, direction = %s", storedFlow.Id,
240 deviceFlow.FlowId, deviceFlow.FlowType))
241 storedFlow.Cookie = flowFromCore.Id
242 f.storedDeviceFlows = append(f.storedDeviceFlows, storedFlow)
Gamze Abakafee36392019-10-03 11:17:24 +0000243 gemPK := gemPortKey{uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId)}
244 flowIDList, ok := f.flowsUsedByGemPort[gemPK]
245 if !ok {
246 flowIDList = []uint32{deviceFlow.FlowId}
247 }
248 flowIDList = appendUnique(flowIDList, deviceFlow.FlowId)
249 f.flowsUsedByGemPort[gemPK] = flowIDList
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400250 log.Debugw("updated Stored flow info", log.Fields{"storedDeviceFlows": f.storedDeviceFlows})
251}
252
salmansiddiqui7ac62132019-08-22 03:58:50 +0000253func (f *OpenOltFlowMgr) divideAndAddFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32,
254 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
255 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) {
Gamze Abakafee36392019-10-03 11:17:24 +0000256 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530257 var gemPorts []uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400258 var TpInst *tp.TechProfile
manikkaraj kbf256be2019-03-25 00:13:48 +0530259
Manikkaraj kb1d51442019-07-23 10:41:02 -0400260 log.Infow("Dividing flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "portNo": portNo,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000261 "classifier": classifierInfo, "action": actionInfo, "UsMeterID": UsMeterID, "DsMeterID": DsMeterID, "TpID": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400262 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
263 // is because the flow is an NNI flow and there would be no onu resources associated with it
264 // TODO: properly deal with NNI flows
Manikkaraj kb1d51442019-07-23 10:41:02 -0400265 if onuID <= 0 {
Matt Jeanneret77199612019-07-26 18:08:35 -0400266 log.Errorw("No onu id for flow", log.Fields{"portNo": portNo, "classifer": classifierInfo, "action": actionInfo})
manikkaraj kbf256be2019-03-25 00:13:48 +0530267 return
268 }
269
Manikkaraj kb1d51442019-07-23 10:41:02 -0400270 uni := getUniPortPath(intfID, onuID, uniID)
271 log.Debugw("Uni port name", log.Fields{"uni": uni})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000272 allocID, gemPorts, TpInst = f.createTcontGemports(intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
Gamze Abakafee36392019-10-03 11:17:24 +0000273 if allocID == 0 || gemPorts == nil || TpInst == nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400274 log.Error("alloc-id-gem-ports-tp-unavailable")
275 return
276 }
277
278 /* Flows can be added specific to gemport if p-bits are received.
279 * If no pbit mentioned then adding flows for all gemports
manikkaraj kbf256be2019-03-25 00:13:48 +0530280 */
Manikkaraj kb1d51442019-07-23 10:41:02 -0400281
282 args := make(map[string]uint32)
Gamze Abakafee36392019-10-03 11:17:24 +0000283 args[IntfID] = intfID
284 args[OnuID] = onuID
285 args[UniID] = uniID
286 args[PortNo] = portNo
287 args[AllocID] = allocID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400288
Gamze Abakafee36392019-10-03 11:17:24 +0000289 f.checkAndAddFlow(args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530290}
291
salmansiddiqui7ac62132019-08-22 03:58:50 +0000292// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
Gamze Abakafee36392019-10-03 11:17:24 +0000293func (f *OpenOltFlowMgr) CreateSchedulerQueues(sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400294
Gamze Abakafee36392019-10-03 11:17:24 +0000295 log.Debugw("CreateSchedulerQueues", log.Fields{"Dir": sq.direction, "IntfID": sq.intfID,
296 "OnuID": sq.onuID, "UniID": sq.uniID, "TpID": sq.tpID, "MeterID": sq.meterID,
297 "TpInst": sq.tpInst, "flowMetadata": sq.flowMetadata})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400298
Gamze Abakafee36392019-10-03 11:17:24 +0000299 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000300 if err != nil {
301 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400302 }
303
304 /* Lets make a simple assumption that if the meter-id is present on the KV store,
305 * then the scheduler and queues configuration is applied on the OLT device
306 * in the given direction.
307 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000308
Manikkaraj kb1d51442019-07-23 10:41:02 -0400309 var SchedCfg *tp_pb.SchedulerConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000310 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400311 if err != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000312 log.Error("Failed to get meter for intf %d, onuid %d, uniid %d", sq.intfID, sq.onuID, sq.uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400313 return err
314 }
315 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000316 if KvStoreMeter.MeterId == sq.meterID {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400317 log.Debug("Scheduler already created for upstream")
318 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400319 }
Gamze Abakafee36392019-10-03 11:17:24 +0000320 log.Errorw("Dynamic meter update not supported", log.Fields{"KvStoreMeterId": KvStoreMeter.MeterId, "MeterID-in-flow": sq.meterID})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000321 return errors.New("invalid-meter-id-in-flow")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400322 }
Gamze Abakafee36392019-10-03 11:17:24 +0000323 log.Debugw("Meter-does-not-exist-Creating-new", log.Fields{"MeterID": sq.meterID, "Direction": Direction})
324 if sq.direction == tp_pb.Direction_UPSTREAM {
325 SchedCfg = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
326 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
327 SchedCfg = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400328 }
329 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000330 if sq.flowMetadata != nil {
331 for _, meter := range sq.flowMetadata.Meters {
332 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400333 meterConfig = meter
334 log.Debugw("Found-meter-config-from-flowmetadata", log.Fields{"meterConfig": meterConfig})
335 break
336 }
337 }
338 } else {
339 log.Error("Flow-metadata-is-not-present-in-flow")
340 }
341 if meterConfig == nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000342 log.Errorw("Could-not-get-meterbands-from-flowMetadata", log.Fields{"flowMetadata": sq.flowMetadata,
343 "MeterID": sq.meterID})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000344 return errors.New("failed-to-get-meter-from-flowMetadata")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400345 } else if len(meterConfig.Bands) < MaxMeterBand {
Gamze Abakafee36392019-10-03 11:17:24 +0000346 log.Errorw("Invalid-number-of-bands-in-meter", log.Fields{"Bands": meterConfig.Bands, "MeterID": sq.meterID})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000347 return errors.New("invalid-number-of-bands-in-meter")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400348 }
349 cir := meterConfig.Bands[0].Rate
350 cbs := meterConfig.Bands[0].BurstSize
351 eir := meterConfig.Bands[1].Rate
352 ebs := meterConfig.Bands[1].BurstSize
353 pir := cir + eir
354 pbs := cbs + ebs
355 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
356
Gamze Abakafee36392019-10-03 11:17:24 +0000357 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Manikkaraj kb1d51442019-07-23 10:41:02 -0400358
359 log.Debugw("Sending Traffic scheduler create to device", log.Fields{"Direction": Direction, "TrafficScheds": TrafficSched})
360 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000361 IntfId: sq.intfID, OnuId: sq.onuID,
362 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400363 TrafficScheds: TrafficSched}); err != nil {
364 log.Errorw("Failed to create traffic schedulers", log.Fields{"error": err})
365 return err
366 }
367 // On receiving the CreateTrafficQueues request, the driver should create corresponding
368 // downstream queues.
Gamze Abakafee36392019-10-03 11:17:24 +0000369 trafficQueues := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400370 log.Debugw("Sending Traffic Queues create to device", log.Fields{"Direction": Direction, "TrafficQueues": trafficQueues})
371 if _, err := f.deviceHandler.Client.CreateTrafficQueues(context.Background(),
Gamze Abakafee36392019-10-03 11:17:24 +0000372 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
373 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400374 TrafficQueues: trafficQueues}); err != nil {
375 log.Errorw("Failed to create traffic queues in device", log.Fields{"error": err})
376 return err
377 }
378
salmansiddiqui7ac62132019-08-22 03:58:50 +0000379 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400380 * store the meter id on the KV store, for further reference.
381 */
Gamze Abakafee36392019-10-03 11:17:24 +0000382 if err := f.resourceMgr.UpdateMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterConfig); err != nil {
383 log.Error("Failed to update meter id for onu %d, meterid %d", sq.onuID, sq.meterID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400384 return err
385 }
386 log.Debugw("updated-meter-info into KV store successfully", log.Fields{"Direction": Direction,
387 "Meter": meterConfig})
388 return nil
389}
390
salmansiddiqui7ac62132019-08-22 03:58:50 +0000391// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
Gamze Abakafee36392019-10-03 11:17:24 +0000392func (f *OpenOltFlowMgr) RemoveSchedulerQueues(sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400393
394 var Direction string
395 var SchedCfg *tp_pb.SchedulerConfig
396 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000397 log.Debugw("Removing schedulers and Queues in OLT", log.Fields{"Direction": sq.direction, "IntfID": sq.intfID,
398 "OnuID": sq.onuID, "UniID": sq.uniID, "UniPort": sq.uniPort})
399 if sq.direction == tp_pb.Direction_UPSTREAM {
400 SchedCfg = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400401 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000402 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
403 SchedCfg = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400404 Direction = "downstream"
405 }
406
Gamze Abakafee36392019-10-03 11:17:24 +0000407 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400408 if err != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000409 log.Errorf("Failed to get Meter for Onu %d", sq.onuID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400410 return err
411 }
412 if KVStoreMeter == nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000413 log.Debugw("No-meter-has-been-installed-yet", log.Fields{"direction": Direction, "IntfID": sq.intfID, "OnuID": sq.onuID, "UniID": sq.uniID})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400414 return nil
415 }
416 cir := KVStoreMeter.Bands[0].Rate
417 cbs := KVStoreMeter.Bands[0].BurstSize
418 eir := KVStoreMeter.Bands[1].Rate
419 ebs := KVStoreMeter.Bands[1].BurstSize
420 pir := cir + eir
421 pbs := cbs + ebs
422
423 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
424
Gamze Abakafee36392019-10-03 11:17:24 +0000425 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
426 TrafficQueues := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400427
428 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(context.Background(),
Gamze Abakafee36392019-10-03 11:17:24 +0000429 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
430 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400431 TrafficQueues: TrafficQueues}); err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000432 log.Errorw("Failed to remove traffic queues", log.Fields{"error": err})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400433 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400434 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000435 log.Debug("Removed traffic queues successfully")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400436 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000437 IntfId: sq.intfID, OnuId: sq.onuID,
438 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400439 TrafficScheds: TrafficSched}); err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000440 log.Errorw("failed to remove traffic schedulers", log.Fields{"error": err})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400441 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400442 }
443
salmansiddiqui7ac62132019-08-22 03:58:50 +0000444 log.Debug("Removed traffic schedulers successfully")
445
446 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400447 * delete the meter id on the KV store.
448 */
Gamze Abakafee36392019-10-03 11:17:24 +0000449 err = f.resourceMgr.RemoveMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400450 if err != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000451 log.Errorf("Failed to remove meter for onu %d, meter id %d", sq.onuID, KVStoreMeter.MeterId)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000452 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400453 }
454 log.Debugw("Removed-meter-from-KV-store successfully", log.Fields{"MeterId": KVStoreMeter.MeterId, "dir": Direction})
455 return err
456}
457
Gamze Abakafee36392019-10-03 11:17:24 +0000458// This function allocates tconts and GEM ports for an ONU
459func (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) {
460 var allocIDs []uint32
461 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530462 var gemPortIDs []uint32
Gamze Abakafee36392019-10-03 11:17:24 +0000463
464 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(intfID, onuID, uniID)
465 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400466
467 tpPath := f.getTPpath(intfID, uni, TpID)
468 // Check tech profile instance already exists for derived port name
salmansiddiqui7ac62132019-08-22 03:58:50 +0000469 techProfileInstance, err := f.techprofile[intfID].GetTPInstanceFromKVStore(TpID, tpPath)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400470 if err != nil { // This should not happen, something wrong in KV backend transaction
471 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": TpID, "path": tpPath})
Gamze Abakafee36392019-10-03 11:17:24 +0000472 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530473 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400474
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700475 log.Debug("Creating New TConts and Gem ports", log.Fields{"pon": intfID, "onu": onuID, "uni": uniID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530476
salmansiddiqui7ac62132019-08-22 03:58:50 +0000477 if techProfileInstance == nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530478 log.Info("Creating tech profile instance", log.Fields{"path": tpPath})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000479 techProfileInstance = f.techprofile[intfID].CreateTechProfInstance(TpID, uni, intfID)
480 if techProfileInstance == nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530481 log.Error("Tech-profile-instance-creation-failed")
Gamze Abakafee36392019-10-03 11:17:24 +0000482 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530483 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000484 f.resourceMgr.UpdateTechProfileIDForOnu(intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530485 } else {
486 log.Debugw("Tech-profile-instance-already-exist-for-given port-name", log.Fields{"uni": uni})
487 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400488 if UsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000489 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
490 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
491 if err := f.CreateSchedulerQueues(sq); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400492 log.Errorw("CreateSchedulerQueues Failed-upstream", log.Fields{"error": err, "meterID": UsMeterID})
Gamze Abakafee36392019-10-03 11:17:24 +0000493 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400494 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530495 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400496 if DsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000497 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
498 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
499 if err := f.CreateSchedulerQueues(sq); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400500 log.Errorw("CreateSchedulerQueues Failed-downstream", log.Fields{"error": err, "meterID": DsMeterID})
Gamze Abakafee36392019-10-03 11:17:24 +0000501 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400502 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530503 }
Gamze Abakafee36392019-10-03 11:17:24 +0000504
505 allocID := techProfileInstance.UsScheduler.AllocID
506 allocIDs = appendUnique(allocIDs, allocID)
507
508 for _, gem := range techProfileInstance.UpstreamGemPortAttributeList {
509 allgemPortIDs = appendUnique(allgemPortIDs, gem.GemportID)
510 gemPortIDs = append(gemPortIDs, gem.GemportID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400511 }
Gamze Abakafee36392019-10-03 11:17:24 +0000512
513 log.Debugw("Allocated Tcont and GEM ports", log.Fields{"allocIDs": allocIDs, "gemports": allgemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530514 // Send Tconts and GEM ports to KV store
Gamze Abakafee36392019-10-03 11:17:24 +0000515 f.storeTcontsGEMPortsIntoKVStore(intfID, onuID, uniID, allocIDs, allgemPortIDs)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000516 return allocID, gemPortIDs, techProfileInstance
manikkaraj kbf256be2019-03-25 00:13:48 +0530517}
518
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700519func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530520
521 log.Debugw("Storing allocated Tconts and GEM ports into KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700522 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "allocID": allocID, "gemPortIDs": gemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530523 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700524 if err := f.resourceMgr.UpdateAllocIdsForOnu(intfID, onuID, uniID, allocID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530525 log.Error("Errow while uploading allocID to KV store")
526 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700527 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(intfID, onuID, uniID, gemPortIDs); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530528 log.Error("Errow while uploading GEMports to KV store")
529 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700530 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(gemPortIDs, intfID, onuID, uniID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530531 log.Error("Errow while uploading gemtopon map to KV store")
532 }
533 log.Debug("Stored tconts and GEM into KV store successfully")
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400534 for _, gemPort := range gemPortIDs {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700535 f.addGemPortToOnuInfoMap(intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400536 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530537}
538
539func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000540 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530541 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000542 for _, intfID := range techRange.IntfIds {
543 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400544 tpCount++
salmansiddiqui7ac62132019-08-22 03:58:50 +0000545 log.Debugw("Init tech profile done", log.Fields{"intfID": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530546 }
547 }
548 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400549 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530550 log.Errorw("Error while populating techprofile",
Manikkaraj kb1d51442019-07-23 10:41:02 -0400551 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000552 return errors.New("error while populating techprofile mgrs")
manikkaraj kbf256be2019-03-25 00:13:48 +0530553 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400554 log.Infow("Populated techprofile for ponports successfully",
555 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
manikkaraj kbf256be2019-03-25 00:13:48 +0530556 return nil
557}
558
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700559func (f *OpenOltFlowMgr) addUpstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530560 portNo uint32, uplinkClassifier map[string]interface{},
561 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700562 allocID uint32, gemportID uint32) {
563 uplinkClassifier[PacketTagType] = SingleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530564 log.Debugw("Adding upstream data flow", log.Fields{"uplinkClassifier": uplinkClassifier, "uplinkAction": uplinkAction})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700565 f.addHSIAFlow(intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700566 Upstream, logicalFlow, allocID, gemportID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530567 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530568}
569
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700570func (f *OpenOltFlowMgr) addDownstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530571 portNo uint32, downlinkClassifier map[string]interface{},
572 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700573 allocID uint32, gemportID uint32) {
574 downlinkClassifier[PacketTagType] = DoubleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530575 log.Debugw("Adding downstream data flow", log.Fields{"downlinkClassifier": downlinkClassifier,
576 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400577 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
578 if vlan, exists := downlinkClassifier[VlanVid]; exists {
579 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700580 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Manikkaraj kb1d51442019-07-23 10:41:02 -0400581 if uint32(metadata.(uint64)) == MkUniPortNum(intfID, onuID, uniID) {
582 log.Infow("Ignoring DL trap device flow from core", log.Fields{"flow": logicalFlow})
583 return
584 }
585 }
586 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530587 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400588
Manikkaraj k884c1242019-04-11 16:26:42 +0530589 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700590 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400591 // vlan_vid is a uint32. must be type asserted as such or conversion fails
592 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530593 if ok {
594 downlinkAction[VlanVid] = dlClVid & 0xfff
595 } else {
596 log.Error("dl-classifier-vid-type-conversion-failed")
597 return
598 }
599
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700600 f.addHSIAFlow(intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700601 Downstream, logicalFlow, allocID, gemportID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530602}
603
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700604func (f *OpenOltFlowMgr) addHSIAFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +0530605 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700606 allocID uint32, gemPortID uint32) {
Manikkaraj k884c1242019-04-11 16:26:42 +0530607 /* One of the OLT platform (Broadcom BAL) requires that symmetric
608 flows require the same flow_id to be used across UL and DL.
609 Since HSIA flow is the only symmetric flow currently, we need to
610 re-use the flow_id across both direction. The 'flow_category'
611 takes priority over flow_cookie to find any available HSIA_FLOW
612 id for the ONU.
613 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700614 log.Debugw("Adding HSIA flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "classifier": classifier,
615 "action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530616 "logicalFlow": *logicalFlow})
Gamze Abakafee36392019-10-03 11:17:24 +0000617 var vlanPbit uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400618 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000619 vlanPbit = classifier[VlanPcp].(uint32)
620 log.Debugw("Found pbit in the flow", log.Fields{"VlanPbit": vlanPbit})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400621 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700622 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Gamze Abakafee36392019-10-03 11:17:24 +0000623 flowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, HsiaFlow, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530624 if err != nil {
625 log.Errorw("Flow id unavailable for HSIA flow", log.Fields{"direction": direction})
626 return
627 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700628 var classifierProto *openoltpb2.Classifier
629 var actionProto *openoltpb2.Action
Manikkaraj k884c1242019-04-11 16:26:42 +0530630 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
631 log.Error("Error in making classifier protobuf for hsia flow")
632 return
633 }
634 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
635 if actionProto = makeOpenOltActionField(action); actionProto == nil {
636 log.Errorw("Error in making action protobuf for hsia flow", log.Fields{"direction": direction})
637 return
638 }
639 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700640 networkIntfID := f.deviceHandler.nniIntfID
641 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
642 OnuId: int32(onuID),
643 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000644 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530645 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700646 AllocId: int32(allocID),
647 NetworkIntfId: int32(networkIntfID),
648 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530649 Classifier: classifierProto,
650 Action: actionProto,
651 Priority: int32(logicalFlow.Priority),
652 Cookie: logicalFlow.Cookie,
653 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400654 if ok := f.addFlowToDevice(logicalFlow, &flow); ok {
Manikkaraj k884c1242019-04-11 16:26:42 +0530655 log.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000656 flowsToKVStore := f.getUpdatedFlowInfo(&flow, flowStoreCookie, HsiaFlow, flowID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530657 if err := f.updateFlowInfoToKVStore(flow.AccessIntfId,
658 flow.OnuId,
659 flow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400660 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530661 log.Errorw("Error uploading HSIA flow into KV store", log.Fields{"flow": flow, "direction": direction, "error": err})
662 return
663 }
664 }
665}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700666func (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 +0530667
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700668 var dhcpFlow openoltpb2.Flow
669 var actionProto *openoltpb2.Action
670 var classifierProto *openoltpb2.Classifier
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530671
672 // Clear the action map
673 for k := range action {
674 delete(action, k)
675 }
676
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700677 action[TrapToHost] = true
678 classifier[UDPSrc] = uint32(68)
679 classifier[UDPDst] = uint32(67)
680 classifier[PacketTagType] = SingleTag
681 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530682
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700683 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530684
Manikkaraj kb1d51442019-07-23 10:41:02 -0400685 flowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, "", 0 /*classifier[VLAN_PCP].(uint32)*/)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530686
687 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700688 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530689 return
690 }
691
692 log.Debugw("Creating UL DHCP flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID})
693
694 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
695 log.Error("Error in making classifier protobuf for ul flow")
696 return
697 }
698 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
699 if actionProto = makeOpenOltActionField(action); actionProto == nil {
700 log.Error("Error in making action protobuf for ul flow")
701 return
702 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700703 networkIntfID := f.deviceHandler.nniIntfID
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530704
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700705 dhcpFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
706 OnuId: int32(onuID),
707 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530708 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700709 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700710 AllocId: int32(allocID),
711 NetworkIntfId: int32(networkIntfID),
712 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530713 Classifier: classifierProto,
714 Action: actionProto,
715 Priority: int32(logicalFlow.Priority),
716 Cookie: logicalFlow.Cookie,
717 PortNo: portNo}
718
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400719 if ok := f.addFlowToDevice(logicalFlow, &dhcpFlow); ok {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530720 log.Debug("DHCP UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400721 flowsToKVStore := f.getUpdatedFlowInfo(&dhcpFlow, flowStoreCookie, "DHCP", flowID)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530722 if err := f.updateFlowInfoToKVStore(dhcpFlow.AccessIntfId,
723 dhcpFlow.OnuId,
724 dhcpFlow.UniId,
725 dhcpFlow.FlowId, flowsToKVStore); err != nil {
726 log.Errorw("Error uploading DHCP UL flow into KV store", log.Fields{"flow": dhcpFlow, "error": err})
727 return
728 }
729 }
730
manikkaraj kbf256be2019-03-25 00:13:48 +0530731 return
732}
733
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700734// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
735func (f *OpenOltFlowMgr) addEAPOLFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, vlanID uint32) {
736 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 +0530737
738 uplinkClassifier := make(map[string]interface{})
739 uplinkAction := make(map[string]interface{})
740 downlinkClassifier := make(map[string]interface{})
741 downlinkAction := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700742 var upstreamFlow openoltpb2.Flow
743 var downstreamFlow openoltpb2.Flow
manikkaraj kbf256be2019-03-25 00:13:48 +0530744
745 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700746 uplinkClassifier[EthType] = uint32(EapEthType)
747 uplinkClassifier[PacketTagType] = SingleTag
748 uplinkClassifier[VlanVid] = vlanID
manikkaraj kbf256be2019-03-25 00:13:48 +0530749 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700750 uplinkAction[TrapToHost] = true
751 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530752 //Add Uplink EAPOL Flow
Manikkaraj kb1d51442019-07-23 10:41:02 -0400753 uplinkFlowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530754 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700755 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manikkaraj k884c1242019-04-11 16:26:42 +0530756 return
manikkaraj kbf256be2019-03-25 00:13:48 +0530757 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700758 var classifierProto *openoltpb2.Classifier
759 var actionProto *openoltpb2.Action
760 log.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530761
762 if classifierProto = makeOpenOltClassifierField(uplinkClassifier); classifierProto == nil {
763 log.Error("Error in making classifier protobuf for ul flow")
764 return
765 }
766 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
767 if actionProto = makeOpenOltActionField(uplinkAction); actionProto == nil {
768 log.Error("Error in making action protobuf for ul flow")
769 return
770 }
771 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700772 networkIntfID := f.deviceHandler.nniIntfID
773 upstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
774 OnuId: int32(onuID),
775 UniId: int32(uniID),
776 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700777 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700778 AllocId: int32(allocID),
779 NetworkIntfId: int32(networkIntfID),
780 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530781 Classifier: classifierProto,
782 Action: actionProto,
783 Priority: int32(logicalFlow.Priority),
784 Cookie: logicalFlow.Cookie,
785 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400786 if ok := f.addFlowToDevice(logicalFlow, &upstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530787 log.Debug("EAPOL UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400788 flowCategory := "EAPOL"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700789 flowsToKVStore := f.getUpdatedFlowInfo(&upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530790 if err := f.updateFlowInfoToKVStore(upstreamFlow.AccessIntfId,
791 upstreamFlow.OnuId,
792 upstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400793 upstreamFlow.FlowId,
794 /* lowCategory, */
795 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530796 log.Errorw("Error uploading EAPOL UL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
797 return
798 }
799 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400800 // Dummy Downstream flow due to BAL 2.6 limitation
801 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530802 /* Add Downstream EAPOL Flow, Only for first EAP flow (BAL
803 # requirement)
804 # On one of the platforms (Broadcom BAL), when same DL classifier
805 # vlan was used across multiple ONUs, eapol flow re-adds after
806 # flow delete (cases of onu reboot/disable) fails.
807 # In order to generate unique vlan, a combination of intf_id
808 # onu_id and uniId is used.
809 # uniId defaults to 0, so add 1 to it.
810 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700811 log.Debugw("Creating DL EAPOL flow with default vlan", log.Fields{"vlan": vlanID})
812 specialVlanDlFlow := 4090 - intfID*onuID*(uniID+1)
manikkaraj kbf256be2019-03-25 00:13:48 +0530813 // Assert that we do not generate invalid vlans under no condition
814 if specialVlanDlFlow <= 2 {
815 log.Fatalw("invalid-vlan-generated", log.Fields{"vlan": specialVlanDlFlow})
816 return
817 }
818 log.Debugw("specialVlanEAPOLDlFlow:", log.Fields{"dl_vlan": specialVlanDlFlow})
819 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700820 downlinkClassifier[PacketTagType] = SingleTag
Manikkaraj kb1d51442019-07-23 10:41:02 -0400821 downlinkClassifier[EthType] = uint32(EapEthType)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700822 downlinkClassifier[VlanVid] = uint32(specialVlanDlFlow)
manikkaraj kbf256be2019-03-25 00:13:48 +0530823 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700824 downlinkAction[PushVlan] = true
825 downlinkAction[VlanVid] = vlanID
826 flowStoreCookie := getFlowStoreCookie(downlinkClassifier, gemPortID)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000827 downlinkFlowID, err := f.resourceMgr.GetFlowID(intfID, onuID, uniID, gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530828 if err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530829 log.Errorw("flowId unavailable for DL EAPOL",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700830 log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
manikkaraj kbf256be2019-03-25 00:13:48 +0530831 return
832 }
833 log.Debugw("Creating DL EAPOL flow",
salmansiddiqui7ac62132019-08-22 03:58:50 +0000834 log.Fields{"dl_classifier": downlinkClassifier, "dl_action": downlinkAction, "downlinkFlowID": downlinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530835 if classifierProto = makeOpenOltClassifierField(downlinkClassifier); classifierProto == nil {
836 log.Error("Error in making classifier protobuf for downlink flow")
837 return
838 }
839 if actionProto = makeOpenOltActionField(downlinkAction); actionProto == nil {
840 log.Error("Error in making action protobuf for dl flow")
841 return
842 }
843 // Downstream flow in grpc protobuf
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700844 downstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
845 OnuId: int32(onuID),
846 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000847 FlowId: downlinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700848 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700849 AllocId: int32(allocID),
850 NetworkIntfId: int32(networkIntfID),
851 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530852 Classifier: classifierProto,
853 Action: actionProto,
854 Priority: int32(logicalFlow.Priority),
855 Cookie: logicalFlow.Cookie,
856 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400857 if ok := f.addFlowToDevice(logicalFlow, &downstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530858 log.Debug("EAPOL DL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400859 flowCategory := ""
salmansiddiqui7ac62132019-08-22 03:58:50 +0000860 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamFlow, flowStoreCookie, flowCategory, downlinkFlowID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530861 if err := f.updateFlowInfoToKVStore(downstreamFlow.AccessIntfId,
862 downstreamFlow.OnuId,
863 downstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400864 downstreamFlow.FlowId,
865 /* flowCategory, */
866 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530867 log.Errorw("Error uploading EAPOL DL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
868 return
869 }
870 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530871 }
872 log.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
873}
874
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700875func makeOpenOltClassifierField(classifierInfo map[string]interface{}) *openoltpb2.Classifier {
876 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -0700877
878 classifier.EthType, _ = classifierInfo[EthType].(uint32)
879 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
880 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
881 vid := vlanID & VlanvIDMask
882 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -0400883 classifier.OVid = vid
884 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530885 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700886 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
887 vid := uint32(metadata)
888 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -0400889 classifier.IVid = vid
890 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530891 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700892 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400893 if vlanPcp == 0 {
894 classifier.OPbits = VlanPCPMask
895 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700896 classifier.OPbits = vlanPcp & VlanPCPMask
Manikkaraj kb1d51442019-07-23 10:41:02 -0400897 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530898 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700899 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
900 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
901 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
902 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
903 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
904 classifier.PktTagType = pktTagType
905
906 switch pktTagType {
907 case SingleTag:
908 case DoubleTag:
909 case Untagged:
910 default:
manikkaraj kbf256be2019-03-25 00:13:48 +0530911 log.Error("Invalid tag type in classifier") // should not hit
912 return nil
913 }
914 }
915 return &classifier
916}
917
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700918func makeOpenOltActionField(actionInfo map[string]interface{}) *openoltpb2.Action {
919 var actionCmd openoltpb2.ActionCmd
920 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +0530921 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700922 if _, ok := actionInfo[PopVlan]; ok {
923 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530924 action.Cmd.RemoveOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700925 } else if _, ok := actionInfo[PushVlan]; ok {
926 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530927 action.Cmd.AddOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700928 } else if _, ok := actionInfo[TrapToHost]; ok {
929 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +0530930 } else {
931 log.Errorw("Invalid-action-field", log.Fields{"action": actionInfo})
932 return nil
933 }
934 return &action
935}
936
Manikkaraj kb1d51442019-07-23 10:41:02 -0400937func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uni string, TpID uint32) string {
938 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530939}
940
Gamze Abakafee36392019-10-03 11:17:24 +0000941// DeleteTechProfileInstances removes the tech profile instances from persistent storage
942func (f *OpenOltFlowMgr) DeleteTechProfileInstances(intfID uint32, onuID uint32, uniID uint32, sn string) error {
943 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(intfID, onuID, uniID)
Devmalya Paul495b94a2019-08-27 19:42:00 -0400944 uniPortName := fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +0000945 for _, tpID := range tpIDList {
946 if err := f.DeleteTechProfileInstance(intfID, onuID, uniID, uniPortName, tpID); err != nil {
947 log.Debugw("Failed-to-delete-tp-instance-from-kv-store", log.Fields{"tp-id": tpID, "uni-port-name": uniPortName})
948 return err
949 }
950 }
951 return nil
952}
953
954// DeleteTechProfileInstance removes the tech profile instance from persistent storage
955func (f *OpenOltFlowMgr) DeleteTechProfileInstance(intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
956 if uniPortName == "" {
957 uniPortName = fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
958 }
Devmalya Paul495b94a2019-08-27 19:42:00 -0400959 if err := f.techprofile[intfID].DeleteTechProfileInstance(tpID, uniPortName); err != nil {
960 log.Debugw("Failed-to-delete-tp-instance-from-kv-store", log.Fields{"tp-id": tpID, "uni-port-name": uniPortName})
961 return err
962 }
963 return nil
964}
965
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700966func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530967 if len(classifier) == 0 { // should never happen
968 log.Error("Invalid classfier object")
969 return 0
970 }
971 var jsonData []byte
972 var flowString string
973 var err error
974 // TODO: Do we need to marshall ??
975 if jsonData, err = json.Marshal(classifier); err != nil {
976 log.Error("Failed to encode classifier")
977 return 0
978 }
979 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700980 if gemPortID != 0 {
981 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +0530982 }
983 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700984 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +0530985 hash := big.NewInt(0)
986 hash.SetBytes(h.Sum(nil))
987 return hash.Uint64()
988}
989
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700990func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openoltpb2.Flow, flowStoreCookie uint64, flowCategory string, deviceFlowID uint32) *[]rsrcMgr.FlowInfo {
991 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
992 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400993 /* For flows which trap out of the NNI, the AccessIntfId is invalid
994 (set to -1). In such cases, we need to refer to the NetworkIntfId .
995 */
996 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700997 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400998 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700999 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001000 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001001 // Get existing flows matching flowid for given subscriber from KV store
1002 existingFlows := f.resourceMgr.GetFlowIDInfo(intfID, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001003 if existingFlows != nil {
1004 log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001005 //for _, f := range *existingFlows {
1006 // flows = append(flows, f)
1007 //}
1008 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001009 }
1010 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 +05301011 return &flows
1012}
1013
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001014//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
1015// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
1016// var intfId uint32
1017// /* For flows which trap out of the NNI, the AccessIntfId is invalid
1018// (set to -1). In such cases, we need to refer to the NetworkIntfId .
1019// */
1020// if flow.AccessIntfId != -1 {
1021// intfId = uint32(flow.AccessIntfId)
1022// } else {
1023// intfId = uint32(flow.NetworkIntfId)
1024// }
1025// // Get existing flows matching flowid for given subscriber from KV store
1026// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
1027// if existingFlows != nil {
1028// log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
1029// for _, f := range *existingFlows {
1030// flows = append(flows, f)
1031// }
1032// }
1033// log.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
1034// return &flows
1035//}
1036
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001037func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
manikkaraj k17652a72019-05-06 09:06:36 -04001038 log.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001039 if err := f.resourceMgr.UpdateFlowIDInfo(intfID, onuID, uniID, flowID, flows); err != nil {
manikkaraj k17652a72019-05-06 09:06:36 -04001040 log.Debug("Error while Storing flow into KV store")
1041 return err
1042 }
1043 log.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +05301044 return nil
1045}
1046
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001047func (f *OpenOltFlowMgr) addFlowToDevice(logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) bool {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001048
1049 var intfID uint32
1050 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1051 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1052 */
1053 if deviceFlow.AccessIntfId != -1 {
1054 intfID = uint32(deviceFlow.AccessIntfId)
1055 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001056 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001057 intfID = uint32(deviceFlow.NetworkIntfId)
1058 }
1059
manikkaraj kbf256be2019-03-25 00:13:48 +05301060 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1061 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001062
1063 st, _ := status.FromError(err)
1064 if st.Code() == codes.AlreadyExists {
Gamze Abakafee36392019-10-03 11:17:24 +00001065 log.Debug("Flow already exists", log.Fields{"err": err, "deviceFlow": deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301066 return false
1067 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001068
1069 if err != nil {
1070 log.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": deviceFlow})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001071 f.resourceMgr.FreeFlowID(intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001072 return false
1073 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001074 log.Debugw("Flow added to device successfully ", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001075 f.registerFlow(logicalFlow, deviceFlow)
1076 return true
1077}
1078
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001079func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) bool {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001080 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1081 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1082 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001083 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
1084 log.Warnw("Can not remove flow from device since it's unreachable", log.Fields{"err": err, "deviceFlow": deviceFlow})
1085 //Assume the flow is removed
1086 return true
1087 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001088 log.Errorw("Failed to Remove flow from device", log.Fields{"err": err, "deviceFlow": deviceFlow})
1089 return false
serkant.uluderya245caba2019-09-24 23:15:29 -07001090
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001091 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001092 log.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301093 return true
1094}
1095
1096/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1097 //update core flows_proxy : flows_proxy.update('/', flows)
1098}
1099
1100func generateStoredId(flowId uint32, direction string)uint32{
1101
David K. Bainbridge82efc492019-09-04 09:57:11 -07001102 if direction == Upstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301103 log.Debug("Upstream flow shifting flowid")
1104 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001105 }else if direction == Downstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301106 log.Debug("Downstream flow not shifting flowid")
1107 return flowId
1108 }else{
1109 log.Errorw("Unrecognized direction",log.Fields{"direction": direction})
1110 return flowId
1111 }
1112}
1113
1114*/
1115
Humera Kouser94d7a842019-08-25 19:04:32 -04001116func (f *OpenOltFlowMgr) addLLDPFlow(flow *ofp.OfpFlowStats, portNo uint32) {
1117
1118 classifierInfo := make(map[string]interface{})
1119 actionInfo := make(map[string]interface{})
1120
1121 classifierInfo[EthType] = uint32(LldpEthType)
1122 classifierInfo[PacketTagType] = Untagged
1123 actionInfo[TrapToHost] = true
1124
1125 // LLDP flow is installed to trap LLDP packets on the NNI port.
1126 // We manage flow_id resource pool on per PON port basis.
1127 // Since this situation is tricky, as a hack, we pass the NNI port
1128 // index (network_intf_id) as PON port Index for the flow_id resource
1129 // pool. Also, there is no ONU Id available for trapping LLDP packets
1130 // on NNI port, use onu_id as -1 (invalid)
1131 // ****************** CAVEAT *******************
1132 // This logic works if the NNI Port Id falls within the same valid
1133 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1134 // we need to have a re-look at this.
1135 // *********************************************
1136
1137 var onuID = -1
1138 var uniID = -1
1139 var gemPortID = -1
1140
1141 var networkInterfaceID = IntfIDFromNniPortNum(portNo)
1142 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
1143 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), flowStoreCookie); present {
1144 log.Debug("Flow-exists--not-re-adding")
1145 return
1146 }
1147 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
1148
1149 if err != nil {
1150 log.Errorw("Flow id unavailable for LLDP traponNNI flow", log.Fields{"error": err})
1151 return
1152 }
1153 var classifierProto *openoltpb2.Classifier
1154 var actionProto *openoltpb2.Action
1155 if classifierProto = makeOpenOltClassifierField(classifierInfo); classifierProto == nil {
1156 log.Error("Error in making classifier protobuf for LLDP trap on nni flow")
1157 return
1158 }
1159 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1160 if actionProto = makeOpenOltActionField(actionInfo); actionProto == nil {
1161 log.Error("Error in making action protobuf for LLDP trap on nni flow")
1162 return
1163 }
1164 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
1165
1166 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1167 OnuId: int32(onuID), // OnuId not required
1168 UniId: int32(uniID), // UniId not used
1169 FlowId: flowID,
1170 FlowType: Downstream,
1171 NetworkIntfId: int32(networkInterfaceID),
1172 GemportId: int32(gemPortID),
1173 Classifier: classifierProto,
1174 Action: actionProto,
1175 Priority: int32(flow.Priority),
1176 Cookie: flow.Cookie,
1177 PortNo: portNo}
1178 if ok := f.addFlowToDevice(flow, &downstreamflow); ok {
1179 log.Debug("LLDP trap on NNI flow added to device successfully")
1180 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID)
1181 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1182 int32(onuID),
1183 int32(uniID),
1184 flowID, flowsToKVStore); err != nil {
1185 log.Errorw("Error uploading LLDP flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1186 }
1187 }
1188 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301189}
1190
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001191func getUniPortPath(intfID uint32, onuID uint32, uniID uint32) string {
1192 return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1193}
1194
1195//getOnuChildDevice to fetch onu
1196func (f *OpenOltFlowMgr) getOnuChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
1197 log.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
1198 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
1199 onuDevice := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301200 if onuDevice == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001201 log.Errorw("onu not found", log.Fields{"intfId": parentPortNo, "onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301202 return nil, errors.New("onu not found")
manikkaraj kbf256be2019-03-25 00:13:48 +05301203 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301204 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1205 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301206}
1207
1208func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001209 log.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301210 return nil
1211}
1212
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001213func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
1214 log.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301215}
1216
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001217func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001218 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001219 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001220 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001221 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001222}
1223
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001224func (f *OpenOltFlowMgr) clearFlowFromResourceManager(flow *ofp.OfpFlowStats, flowID uint32, flowDirection string) {
1225 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowID": flowID, "flowDirection": flowDirection, "flow": *flow})
Humera Kouser94d7a842019-08-25 19:04:32 -04001226 portNum, ponIntf, onuID, uniID, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001227 if err != nil {
1228 log.Error(err)
1229 return
1230 }
1231 log.Debugw("Extracted access info from flow to be deleted",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001232 log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001233
Humera Kouser94d7a842019-08-25 19:04:32 -04001234 if ethType == LldpEthType {
1235 var networkInterfaceID uint32
1236 var onuID = -1
1237 var uniID = -1
1238
1239 networkInterfaceID = IntfIDFromNniPortNum(inPort)
1240 f.resourceMgr.FreeFlowID(networkInterfaceID, int32(onuID), int32(uniID), flowID)
1241 return
1242 }
1243
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001244 flowsInfo := f.resourceMgr.GetFlowIDInfo(ponIntf, onuID, uniID, flowID)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001245 if flowsInfo == nil {
Gamze Abakafee36392019-10-03 11:17:24 +00001246 log.Debugw("No FlowInfo found in KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001247 log.Fields{"ponIntf": ponIntf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001248 return
1249 }
1250 var updatedFlows []rsrcMgr.FlowInfo
Gamze Abakafee36392019-10-03 11:17:24 +00001251 var gemPortID int32
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001252
1253 for _, flow := range *flowsInfo {
1254 updatedFlows = append(updatedFlows, flow)
1255 }
1256
1257 for i, storedFlow := range updatedFlows {
1258 if flowDirection == storedFlow.Flow.FlowType {
1259 //Remove the Flow from FlowInfo
1260 log.Debugw("Removing flow to be deleted", log.Fields{"flow": storedFlow})
Gamze Abakafee36392019-10-03 11:17:24 +00001261 gemPortID = storedFlow.Flow.GemportId
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001262 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1263 break
1264 }
1265 }
1266
Gamze Abakafee36392019-10-03 11:17:24 +00001267 tpID := getTpIDFromFlow(flow)
1268
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001269 if len(updatedFlows) >= 0 {
1270 // There are still flows referencing the same flow_id.
1271 // So the flow should not be freed yet.
1272 // For ex: Case of HSIA where same flow is shared
1273 // between DS and US.
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001274 f.updateFlowInfoToKVStore(int32(ponIntf), int32(onuID), int32(uniID), flowID, &updatedFlows)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001275 if len(updatedFlows) == 0 {
1276 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 -04001277 f.resourceMgr.FreeFlowID(ponIntf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001278
Gamze Abakafee36392019-10-03 11:17:24 +00001279 uni := getUniPortPath(ponIntf, onuID, uniID)
1280 tpPath := f.getTPpath(ponIntf, uni, tpID)
1281 log.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
1282 techprofileInst, err := f.techprofile[ponIntf].GetTPInstanceFromKVStore(tpID, tpPath)
1283 if err != nil { // This should not happen, something wrong in KV backend transaction
1284 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": 20, "path": tpPath})
1285 return
1286 }
1287 if techprofileInst == nil {
1288 log.Errorw("Tech-profile-instance-does-not-exist-in-KV Store", log.Fields{"tpPath": tpPath})
1289 return
1290 }
1291
1292 gemPK := gemPortKey{ponIntf, uint32(gemPortID)}
1293 if f.isGemPortUsedByAnotherFlow(gemPK) {
1294 flowIDs := f.flowsUsedByGemPort[gemPK]
1295 for i, flowIDinMap := range flowIDs {
1296 if flowIDinMap == flowID {
1297 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
1298 f.flowsUsedByGemPort[gemPK] = flowIDs
1299 break
1300 }
1301 }
1302 log.Debugw("Gem port id is still used by other flows", log.Fields{"gemPortID": gemPortID, "usedByFlows": flowIDs})
1303 return
1304 }
1305
1306 log.Debugf("Gem port id %d is not used by another flow - releasing the gem port", gemPortID)
1307 f.resourceMgr.RemoveGemPortIDForOnu(ponIntf, onuID, uniID, uint32(gemPortID))
1308 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1309 // But it is anyway eventually removed later when the TechProfile is freed, so not a big issue for now.
1310 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(uint32(gemPortID), ponIntf)
1311 f.onuIdsLock.Lock()
1312 delete(f.flowsUsedByGemPort, gemPK)
1313 delete(f.onuGemPortIds, gemPK)
1314 f.resourceMgr.FreeGemPortID(ponIntf, onuID, uniID, uint32(gemPortID))
1315 f.onuIdsLock.Unlock()
1316
1317 ok, _ := f.isTechProfileUsedByAnotherGem(ponIntf, onuID, uniID, techprofileInst, uint32(gemPortID))
1318 if !ok {
1319 f.resourceMgr.RemoveTechProfileIDForOnu(ponIntf, onuID, uniID, tpID)
1320 f.RemoveSchedulerQueues(schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: ponIntf, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1321 f.RemoveSchedulerQueues(schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: ponIntf, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1322 f.DeleteTechProfileInstance(ponIntf, onuID, uniID, "", tpID)
1323 f.resourceMgr.FreeAllocID(ponIntf, onuID, uniID, techprofileInst.UsScheduler.AllocID)
1324 // TODO: Send a "Delete TechProfile" message to ONU to do its own clean up on ONU OMCI stack
1325 }
1326 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001327 }
1328}
1329
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001330//RemoveFlow removes the flow from the device
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001331func (f *OpenOltFlowMgr) RemoveFlow(flow *ofp.OfpFlowStats) {
1332 log.Debugw("Removing Flow", log.Fields{"flow": flow})
1333 var deviceFlowsToRemove []ofp.OfpFlowStats
1334 var deletedFlowsIdx []int
1335 for _, curFlow := range f.storedDeviceFlows {
1336 if curFlow.Cookie == flow.Id {
1337 log.Debugw("Found found matching flow-cookie", log.Fields{"curFlow": curFlow})
1338 deviceFlowsToRemove = append(deviceFlowsToRemove, curFlow)
1339 }
1340 }
1341 log.Debugw("Flows to be deleted", log.Fields{"deviceFlowsToRemove": deviceFlowsToRemove})
1342 for index, curFlow := range deviceFlowsToRemove {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001343 id, direction := f.decodeStoredID(curFlow.GetId())
1344 removeFlowMessage := openoltpb2.Flow{FlowId: uint32(id), FlowType: direction}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001345 if ok := f.removeFlowFromDevice(&removeFlowMessage); ok {
1346 log.Debug("Flow removed from device successfully")
1347 deletedFlowsIdx = append(deletedFlowsIdx, index)
1348 f.clearFlowFromResourceManager(flow, uint32(id), direction) //TODO: Take care of the limitations
1349 }
1350
1351 }
1352 // Can be done in separate go routine as it takes time ?
1353 for _, flowToRemove := range deletedFlowsIdx {
1354 for index, storedFlow := range f.storedDeviceFlows {
1355 if deviceFlowsToRemove[flowToRemove].Cookie == storedFlow.Cookie {
1356 log.Debugw("Removing flow from local Store", log.Fields{"flow": storedFlow})
1357 f.storedDeviceFlows = append(f.storedDeviceFlows[:index], f.storedDeviceFlows[index+1:]...)
1358 break
1359 }
1360 }
1361 }
1362 log.Debugw("Flows removed from the data store",
1363 log.Fields{"number_of_flows_removed": len(deviceFlowsToRemove), "updated_stored_flows": f.storedDeviceFlows})
1364 return
1365}
1366
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001367// AddFlow add flow to device
Manikkaraj kb1d51442019-07-23 10:41:02 -04001368func (f *OpenOltFlowMgr) AddFlow(flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001369 classifierInfo := make(map[string]interface{})
1370 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001371 var UsMeterID uint32
1372 var DsMeterID uint32
1373
1374 log.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001375 formulateClassifierInfoFromFlow(classifierInfo, flow)
1376
1377 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
1378 if err != nil {
1379 // Error logging is already done in the called function
1380 // So just return in case of error
1381 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301382 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001383
manikkaraj k17652a72019-05-06 09:06:36 -04001384 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00001385 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
1386 if err != nil {
1387 // error if any, already logged in the called function
1388 return
manikkaraj k17652a72019-05-06 09:06:36 -04001389 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001390
David K. Bainbridge82efc492019-09-04 09:57:11 -07001391 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[Output]})
1392 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00001393
Humera Kouser94d7a842019-08-25 19:04:32 -04001394 if ethType, ok := classifierInfo[EthType]; ok {
1395 if ethType.(uint32) == LldpEthType {
1396 log.Info("Adding LLDP flow")
1397 f.addLLDPFlow(flow, portNo)
1398 return
1399 }
1400 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001401 if ipProto, ok := classifierInfo[IPProto]; ok {
1402 if ipProto.(uint32) == IPProtoDhcp {
1403 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001404 if udpSrc.(uint32) == uint32(67) {
1405 log.Debug("trap-dhcp-from-nni-flow")
1406 f.addDHCPTrapFlowOnNNI(flow, classifierInfo, portNo)
1407 return
1408 }
1409 }
1410 }
1411 }
A R Karthick1f85b802019-10-11 05:06:05 +00001412
1413 f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
1414
Gamze Abakafee36392019-10-03 11:17:24 +00001415 TpID := getTpIDFromFlow(flow)
1416
salmansiddiqui7ac62132019-08-22 03:58:50 +00001417 log.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001418 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07001419 UsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001420 log.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
1421 } else {
Scott Baker355d1742019-10-24 10:57:52 -07001422 DsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001423 log.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
1424
1425 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001426 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001427}
1428
1429//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04001430func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001431
1432 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301433 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001434 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301435 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301436 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301437 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04001438
Manikkaraj kb1d51442019-07-23 10:41:02 -04001439 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001440 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
manikkaraj k17652a72019-05-06 09:06:36 -04001441 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
1442 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1443 tpDownloadMsg,
1444 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
1445 f.deviceHandler.deviceType,
1446 onuDevice.Type,
1447 onuDevice.Id,
1448 onuDevice.ProxyAddress.DeviceId, "")
1449 if sendErr != nil {
1450 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1451 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1452 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1453 return sendErr
1454 }
1455 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05301456 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301457}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001458
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001459//UpdateOnuInfo function adds onu info to cache
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001460func (f *OpenOltFlowMgr) UpdateOnuInfo(intfID uint32, onuID uint32, serialNum string) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001461 onu := onuInfo{intfID: intfID, onuID: onuID, serialNumber: serialNum}
1462 onuIDkey := onuIDKey{intfID: intfID, onuID: onuID}
William Kurkian740a09c2019-10-23 17:07:38 -04001463 f.onuIdsLock.Lock()
1464 defer f.onuIdsLock.Unlock()
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001465 f.onuIds[onuIDkey] = onu
1466 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
1467}
1468
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001469//addGemPortToOnuInfoMap function stores adds GEMport to ONU map
1470func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(intfID uint32, onuID uint32, gemPort uint32) {
1471 onuIDkey := onuIDKey{intfID: intfID, onuID: onuID}
William Kurkian740a09c2019-10-23 17:07:38 -04001472 f.onuIdsLock.RLock()
1473 defer f.onuIdsLock.RUnlock()
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001474 if val, ok := f.onuIds[onuIDkey]; ok {
kdarapu3248f9a2019-10-03 13:54:52 +05301475 onuInf := val
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001476 gemportKey := gemPortKey{intfID: intfID, gemPort: gemPort}
kdarapu3248f9a2019-10-03 13:54:52 +05301477 f.onuGemPortIds[gemportKey] = onuInf
1478 log.Debugw("Cached Gemport to Onuinfo map", log.Fields{"GemPort": gemPort, "intfId": onuInf.intfID, "onuId": onuInf.onuID})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001479 return
1480 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001481 log.Errorw("OnuInfo not found", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001482}
1483
1484// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001485
1486//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
1487func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
1488 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 -04001489 if serialNumber != "" {
kdarapu3248f9a2019-10-03 13:54:52 +05301490 if onuInf, ok := f.onuSerialNumbers[serialNumber]; ok {
1491 return onuInf.onuID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001492 }
1493 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001494 gemportKey := gemPortKey{intfID: intfID, gemPort: gemPortID}
kdarapu3248f9a2019-10-03 13:54:52 +05301495 if onuInf, ok := f.onuGemPortIds[gemportKey]; ok {
1496 log.Debugw("Retrieved onu info from access", log.Fields{"intfId": intfID, "gemPortId": gemPortID, "onuId": onuInf.onuID})
1497 return onuInf.onuID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001498 }
1499 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001500 log.Errorw("onuid is not found", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPort": gemPortID})
1501 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 -04001502}
1503
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001504//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
1505func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001506 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001507 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001508 var err error
1509
1510 if packetIn.IntfType == "pon" {
1511 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001512 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001513 log.Errorw("Unable to get ONU ID from GEM/PON port", log.Fields{"pon port": packetIn.IntfId, "gemport": packetIn.GemportId})
1514 return logicalPortNum, err
1515 }
1516 if packetIn.PortNo != 0 {
1517 logicalPortNum = packetIn.PortNo
1518 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001519 uniID := uint32(0) // FIXME - multi-uni support
1520 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001521 }
1522 // 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 -07001523 pktInkey := packetInInfoKey{intfID: packetIn.IntfId, onuID: onuID, logicalPort: logicalPortNum}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001524 f.packetInGemPort[pktInkey] = packetIn.GemportId
1525 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001526 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001527 }
1528 log.Debugw("Retrieved logicalport from packet-in", log.Fields{"logicalPortNum": logicalPortNum, "IntfType": packetIn.IntfType})
1529 return logicalPortNum, nil
1530}
1531
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001532//GetPacketOutGemPortID returns gemPortId
1533func (f *OpenOltFlowMgr) GetPacketOutGemPortID(intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
1534 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001535 var err error
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001536 key := packetInInfoKey{intfID: intfID, onuID: onuID, logicalPort: portNum}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001537 if val, ok := f.packetInGemPort[key]; ok {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001538 gemPortID = val
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001539 } else {
1540 log.Errorw("Key-Error while fetching packet-out GEM port", log.Fields{"key": key})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001541 err = errors.New("key-error while fetching packet-out GEM port")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001542 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001543 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001544}
1545
Manikkaraj kb1d51442019-07-23 10:41:02 -04001546func installFlowOnAllGemports(
1547 f1 func(intfId uint32, onuId uint32, uniId uint32,
1548 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
1549 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32),
1550 f2 func(intfId uint32, onuId uint32, uniId uint32, portNo uint32,
1551 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32),
1552 args map[string]uint32,
1553 classifier map[string]interface{}, action map[string]interface{},
1554 logicalFlow *ofp.OfpFlowStats,
1555 gemPorts []uint32,
1556 FlowType string,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001557 vlanID ...uint32) {
1558 log.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
1559 for _, gemPortID := range gemPorts {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001560 if FlowType == HsiaFlow || FlowType == DhcpFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001561 f1(args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001562 } else if FlowType == EapolFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001563 f2(args["intfId"], args["onuId"], args["uniId"], args["portNo"], logicalFlow, args["allocId"], gemPortID, vlanID[0])
Manikkaraj kb1d51442019-07-23 10:41:02 -04001564 } else {
1565 log.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
1566 return
1567 }
1568 }
1569}
1570
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001571func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
1572 log.Debug("Adding trap-dhcp-of-nni-flow")
1573 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001574 classifier[PacketTagType] = DoubleTag
1575 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001576 /* We manage flowId resource pool on per PON port basis.
1577 Since this situation is tricky, as a hack, we pass the NNI port
1578 index (network_intf_id) as PON port Index for the flowId resource
1579 pool. Also, there is no ONU Id available for trapping DHCP packets
1580 on NNI port, use onu_id as -1 (invalid)
1581 ****************** CAVEAT *******************
1582 This logic works if the NNI Port Id falls within the same valid
1583 range of PON Port Ids. If this doesn't work for some OLT Vendor
1584 we need to have a re-look at this.
1585 *********************************************
1586 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001587 onuID := -1
1588 uniID := -1
1589 gemPortID := -1
1590 allocID := -1
1591 networkInterfaceID := f.deviceHandler.nniIntfID
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001592 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001593 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), flowStoreCookie); present {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001594 log.Debug("Flow-exists--not-re-adding")
1595 return
1596 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001597 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), uint32(onuID), uint32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001598 if err != nil {
1599 log.Errorw("Flow id unavailable for DHCP traponNNI flow", log.Fields{"error": err})
1600 return
1601 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001602 var classifierProto *openoltpb2.Classifier
1603 var actionProto *openoltpb2.Action
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001604 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
1605 log.Error("Error in making classifier protobuf for dhcp trap on nni flow")
1606 return
1607 }
1608 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1609 if actionProto = makeOpenOltActionField(action); actionProto == nil {
1610 log.Error("Error in making action protobuf for dhcp trap on nni flow")
1611 return
1612 }
1613 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001614 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1615 OnuId: int32(onuID), // OnuId not required
1616 UniId: int32(uniID), // UniId not used
1617 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001618 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001619 AllocId: int32(allocID), // AllocId not used
1620 NetworkIntfId: int32(networkInterfaceID),
1621 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001622 Classifier: classifierProto,
1623 Action: actionProto,
1624 Priority: int32(logicalFlow.Priority),
1625 Cookie: logicalFlow.Cookie,
1626 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001627 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001628 log.Debug("DHCP trap on NNI flow added to device successfully")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001629 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID)
1630 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1631 int32(onuID),
1632 int32(uniID),
1633 flowID, flowsToKVStore); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001634 log.Errorw("Error uploading DHCP DL flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1635 }
1636 }
1637 return
1638}
salmansiddiqui7ac62132019-08-22 03:58:50 +00001639
1640func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
1641 if MeterID == 0 { // This should never happen
1642 log.Error("Invalid meter id")
1643 return "", errors.New("invalid meter id")
1644 }
1645 if Dir == tp_pb.Direction_UPSTREAM {
1646 return "upstream", nil
1647 } else if Dir == tp_pb.Direction_DOWNSTREAM {
1648 return "downstream", nil
1649 }
1650 return "", nil
1651}
1652
1653func (f *OpenOltFlowMgr) checkAndAddFlow(args map[string]uint32, classifierInfo map[string]interface{},
Gamze Abakafee36392019-10-03 11:17:24 +00001654 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst *tp.TechProfile, gemPorts []uint32,
1655 TpID uint32, uni string) {
1656 var gemPort uint32
1657 intfID := args[IntfID]
1658 onuID := args[OnuID]
1659 uniID := args[UniID]
1660 portNo := args[PortNo]
1661 allocID := TpInst.UsScheduler.AllocID
salmansiddiqui7ac62132019-08-22 03:58:50 +00001662 if ipProto, ok := classifierInfo[IPProto]; ok {
1663 if ipProto.(uint32) == IPProtoDhcp {
1664 log.Info("Adding DHCP flow")
1665 if pcp, ok := classifierInfo[VlanPcp]; ok {
1666 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1667 tp_pb.Direction_UPSTREAM,
1668 pcp.(uint32))
1669 //Adding DHCP upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001670 f.addDHCPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001671 } else {
1672 //Adding DHCP upstream flow to all gemports
1673 installFlowOnAllGemports(f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, DhcpFlow)
1674 }
1675
1676 } else if ipProto == IgmpProto {
1677 log.Info("igmp flow add ignored, not implemented yet")
1678 return
1679 } else {
1680 log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
1681 return
1682 }
1683 } else if ethType, ok := classifierInfo[EthType]; ok {
1684 if ethType.(uint32) == EapEthType {
1685 log.Info("Adding EAPOL flow")
1686 var vlanID uint32
1687 if val, ok := classifierInfo[VlanVid]; ok {
1688 vlanID = (val.(uint32)) & VlanvIDMask
1689 } else {
1690 vlanID = DefaultMgmtVlan
1691 }
1692 if pcp, ok := classifierInfo[VlanPcp]; ok {
1693 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1694 tp_pb.Direction_UPSTREAM,
1695 pcp.(uint32))
1696
Gamze Abakafee36392019-10-03 11:17:24 +00001697 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID, gemPort, vlanID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001698 } else {
1699 installFlowOnAllGemports(nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, EapolFlow, vlanID)
1700 }
1701 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001702 } else if _, ok := actionInfo[PushVlan]; ok {
1703 log.Info("Adding upstream data rule")
1704 if pcp, ok := classifierInfo[VlanPcp]; ok {
1705 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1706 tp_pb.Direction_UPSTREAM,
1707 pcp.(uint32))
1708 //Adding HSIA upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001709 f.addUpstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001710 } else {
1711 //Adding HSIA upstream flow to all gemports
1712 installFlowOnAllGemports(f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1713 }
1714 } else if _, ok := actionInfo[PopVlan]; ok {
1715 log.Info("Adding Downstream data rule")
1716 if pcp, ok := classifierInfo[VlanPcp]; ok {
1717 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05001718 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001719 pcp.(uint32))
1720 //Adding HSIA downstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001721 f.addDownstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001722 } else {
1723 //Adding HSIA downstream flow to all gemports
1724 installFlowOnAllGemports(f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1725 }
1726 } else {
1727 log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
1728 return
1729 }
1730 // Send Techprofile download event to child device in go routine as it takes time
1731 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, TpID)
1732}
1733
Gamze Abakafee36392019-10-03 11:17:24 +00001734func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
1735 flowIDList := f.flowsUsedByGemPort[gemPK]
1736 if len(flowIDList) > 1 {
1737 return true
1738 }
1739 return false
1740}
1741
1742func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ponIntf uint32, onuID uint32, uniID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
1743 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ponIntf, onuID, uniID)
1744 tpGemPorts := tpInst.UpstreamGemPortAttributeList
1745 for _, currentGemPort := range currentGemPorts {
1746 for _, tpGemPort := range tpGemPorts {
1747 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
1748 return true, currentGemPort
1749 }
1750 }
1751 }
1752 return false, 0
1753}
1754
salmansiddiqui7ac62132019-08-22 03:58:50 +00001755func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07001756 for _, field := range flows.GetOfbFields(flow) {
1757 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001758 classifierInfo[EthType] = field.GetEthType()
1759 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001760 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001761 classifierInfo[IPProto] = field.GetIpProto()
1762 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001763 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001764 classifierInfo[InPort] = field.GetPort()
1765 log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001766 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05301767 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
salmansiddiqui7ac62132019-08-22 03:58:50 +00001768 log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001769 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001770 classifierInfo[VlanPcp] = field.GetVlanPcp()
1771 log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001772 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001773 classifierInfo[UDPDst] = field.GetUdpDst()
1774 log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001775 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001776 classifierInfo[UDPSrc] = field.GetUdpSrc()
1777 log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001778 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001779 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
1780 log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001781 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001782 classifierInfo[Ipv4Src] = field.GetIpv4Src()
1783 log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001784 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001785 classifierInfo[Metadata] = field.GetTableMetadata()
1786 log.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07001787 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001788 classifierInfo[TunnelID] = field.GetTunnelId()
1789 log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
1790 } else {
1791 log.Errorw("Un supported field type", log.Fields{"type": field.Type})
1792 return
1793 }
1794 }
1795}
1796
1797func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07001798 for _, action := range flows.GetActions(flow) {
1799 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001800 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001801 actionInfo[Output] = out.GetPort()
1802 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001803 } else {
1804 log.Error("Invalid output port in action")
1805 return errors.New("invalid output port in action")
1806 }
Scott Baker355d1742019-10-24 10:57:52 -07001807 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001808 actionInfo[PopVlan] = true
1809 log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001810 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001811 if out := action.GetPush(); out != nil {
1812 if tpid := out.GetEthertype(); tpid != 0x8100 {
1813 log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
1814 } else {
1815 actionInfo[PushVlan] = true
1816 actionInfo[TPID] = tpid
1817 log.Debugw("action-type-push-vlan",
1818 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
1819 }
1820 }
Scott Baker355d1742019-10-24 10:57:52 -07001821 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001822 if out := action.GetSetField(); out != nil {
1823 if field := out.GetField(); field != nil {
1824 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
1825 log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
1826 return errors.New("invalid openflow class")
1827 }
1828 /*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
1829 if ofbField := field.GetOfbField(); ofbField != nil {
1830 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
1831 if vlan := ofbField.GetVlanVid(); vlan != 0 {
1832 actionInfo[VlanVid] = vlan & 0xfff
1833 log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
1834 } else {
1835 log.Error("No Invalid vlan id in set vlan-vid action")
1836 }
1837 } else {
1838 log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
1839 }
1840 }
1841 }
1842 }
1843 } else {
1844 log.Errorw("Un supported action type", log.Fields{"type": action.Type})
1845 return errors.New("un supported action type")
1846 }
1847 }
1848 return nil
1849}
1850
1851func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001852 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001853 log.Debug("Controller bound trap flows, getting inport from tunnelid")
1854 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
1855 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001856 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001857 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07001858 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 +00001859 } else {
1860 log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1861 return errors.New("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1862 }
1863 }
1864 } else {
1865 log.Debug("Non-Controller flows, getting uniport from tunnelid")
1866 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07001867 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001868 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001869 actionInfo[Output] = uniPort
1870 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 +00001871 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001872 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 +00001873 return errors.New("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid")
1874 }
1875 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
1876 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001877 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001878 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07001879 log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[Output].(uint32),
1880 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001881 } else {
1882 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 -07001883 "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001884 return errors.New("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid")
1885 }
1886 }
1887 }
1888 return nil
1889}
Gamze Abakafee36392019-10-03 11:17:24 +00001890
1891func getTpIDFromFlow(flow *ofp.OfpFlowStats) uint32 {
1892 /* Metadata 8 bytes:
1893 Most Significant 2 Bytes = Inner VLAN
1894 Next 2 Bytes = Tech Profile ID(TPID)
1895 Least Significant 4 Bytes = Port ID
1896 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
1897 subscriber related flows.
1898 */
1899 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
1900 if metadata == 0 {
1901 log.Error("Metadata is not present in flow which is mandatory")
1902 return 0
1903 }
1904 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
1905 return uint32(TpID)
1906}
1907
1908func appendUnique(slice []uint32, item uint32) []uint32 {
1909 for _, sliceElement := range slice {
1910 if sliceElement == item {
1911 return slice
1912 }
1913 }
1914 return append(slice, item)
1915}