blob: 9eddc445e3e83e414e5fd0647b6724c440459b9f [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"
Scott Bakerc6e54cb2019-11-04 09:31:25 -080033 "github.com/opencord/voltha-protos/v2/go/common"
34 ic "github.com/opencord/voltha-protos/v2/go/inter_container"
35 ofp "github.com/opencord/voltha-protos/v2/go/openflow_13"
36 openoltpb2 "github.com/opencord/voltha-protos/v2/go/openolt"
37 tp_pb "github.com/opencord/voltha-protos/v2/go/tech_profile"
38 "github.com/opencord/voltha-protos/v2/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 gemPortKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700152 intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400153 gemPort uint32
154}
155
Gamze Abakafee36392019-10-03 11:17:24 +0000156type schedQueue struct {
157 direction tp_pb.Direction
158 intfID uint32
159 onuID uint32
160 uniID uint32
161 tpID uint32
162 uniPort uint32
163 tpInst *tp.TechProfile
164 meterID uint32
165 flowMetadata *voltha.FlowMetadata
166}
167
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700168//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530169type OpenOltFlowMgr struct {
Gamze Abakafee36392019-10-03 11:17:24 +0000170 techprofile []tp.TechProfileIf
171 deviceHandler *DeviceHandler
172 resourceMgr *rsrcMgr.OpenOltResourceMgr
Gamze Abakafee36392019-10-03 11:17:24 +0000173 onuIdsLock sync.RWMutex
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530174 flowsUsedByGemPort map[gemPortKey][]uint32 //gem port id to flow ids
175 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
176 onuGemInfo map[uint32][]rsrcMgr.OnuGemInfo //onu, gem and uni info local cache
177 lockCache sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +0530178}
179
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700180//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530181func NewFlowManager(dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
manikkaraj kbf256be2019-03-25 00:13:48 +0530182 log.Info("Initializing flow manager")
183 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530184 var err error
185 var idx uint32
186
manikkaraj kbf256be2019-03-25 00:13:48 +0530187 flowMgr.deviceHandler = dh
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530188 flowMgr.resourceMgr = rMgr
kdarapub26b4502019-10-05 03:02:33 +0530189 flowMgr.techprofile = make([]tp.TechProfileIf, MaxPonPorts)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530190 if err = flowMgr.populateTechProfilePerPonPort(); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530191 log.Error("Error while populating tech profile mgr\n")
192 return nil
193 }
William Kurkian740a09c2019-10-23 17:07:38 -0400194 flowMgr.onuIdsLock = sync.RWMutex{}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530195 flowMgr.flowsUsedByGemPort = make(map[gemPortKey][]uint32)
196 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
197 flowMgr.onuGemInfo = make(map[uint32][]rsrcMgr.OnuGemInfo)
198 ponPorts := rMgr.DevInfo.GetPonPorts()
199 //Load the onugem info cache from kv store on flowmanager start
200 for idx = 0; idx < ponPorts; idx++ {
201 if flowMgr.onuGemInfo[idx], err = rMgr.GetOnuGemInfo(idx); err != nil {
202 log.Error("Failed to load onu gem info cache")
203 }
204 }
205 flowMgr.lockCache = sync.RWMutex{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530206 log.Info("Initialization of flow manager success!!")
207 return &flowMgr
208}
209
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700210func (f *OpenOltFlowMgr) generateStoredFlowID(flowID uint32, direction string) (uint64, error) {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700211 if direction == Upstream {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400212 log.Debug("upstream flow, shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700213 return 0x1<<15 | uint64(flowID), nil
David K. Bainbridge82efc492019-09-04 09:57:11 -0700214 } else if direction == Downstream {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400215 log.Debug("downstream flow, not shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700216 return uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400217 } else {
218 log.Debug("Unrecognized direction")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700219 return 0, fmt.Errorf("unrecognized direction %s", direction)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400220 }
221}
222
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700223func (f *OpenOltFlowMgr) registerFlow(flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400224 log.Debug("Registering Flow for Device ", log.Fields{"flow": flowFromCore},
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700225 log.Fields{"device": f.deviceHandler.deviceID})
Gamze Abakafee36392019-10-03 11:17:24 +0000226 gemPK := gemPortKey{uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId)}
227 flowIDList, ok := f.flowsUsedByGemPort[gemPK]
228 if !ok {
229 flowIDList = []uint32{deviceFlow.FlowId}
230 }
231 flowIDList = appendUnique(flowIDList, deviceFlow.FlowId)
232 f.flowsUsedByGemPort[gemPK] = flowIDList
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400233}
234
salmansiddiqui7ac62132019-08-22 03:58:50 +0000235func (f *OpenOltFlowMgr) divideAndAddFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32,
236 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
237 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) {
Gamze Abakafee36392019-10-03 11:17:24 +0000238 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530239 var gemPorts []uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400240 var TpInst *tp.TechProfile
manikkaraj kbf256be2019-03-25 00:13:48 +0530241
Manikkaraj kb1d51442019-07-23 10:41:02 -0400242 log.Infow("Dividing flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "portNo": portNo,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000243 "classifier": classifierInfo, "action": actionInfo, "UsMeterID": UsMeterID, "DsMeterID": DsMeterID, "TpID": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400244 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
245 // is because the flow is an NNI flow and there would be no onu resources associated with it
246 // TODO: properly deal with NNI flows
Manikkaraj kb1d51442019-07-23 10:41:02 -0400247 if onuID <= 0 {
Matt Jeanneret77199612019-07-26 18:08:35 -0400248 log.Errorw("No onu id for flow", log.Fields{"portNo": portNo, "classifer": classifierInfo, "action": actionInfo})
manikkaraj kbf256be2019-03-25 00:13:48 +0530249 return
250 }
251
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530252 uni := getUniPortPath(intfID, int32(onuID), int32(uniID))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400253 log.Debugw("Uni port name", log.Fields{"uni": uni})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000254 allocID, gemPorts, TpInst = f.createTcontGemports(intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
Gamze Abakafee36392019-10-03 11:17:24 +0000255 if allocID == 0 || gemPorts == nil || TpInst == nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400256 log.Error("alloc-id-gem-ports-tp-unavailable")
257 return
258 }
259
260 /* Flows can be added specific to gemport if p-bits are received.
261 * If no pbit mentioned then adding flows for all gemports
manikkaraj kbf256be2019-03-25 00:13:48 +0530262 */
Manikkaraj kb1d51442019-07-23 10:41:02 -0400263
264 args := make(map[string]uint32)
Gamze Abakafee36392019-10-03 11:17:24 +0000265 args[IntfID] = intfID
266 args[OnuID] = onuID
267 args[UniID] = uniID
268 args[PortNo] = portNo
269 args[AllocID] = allocID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400270
Gamze Abakafee36392019-10-03 11:17:24 +0000271 f.checkAndAddFlow(args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530272}
273
salmansiddiqui7ac62132019-08-22 03:58:50 +0000274// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
Gamze Abakafee36392019-10-03 11:17:24 +0000275func (f *OpenOltFlowMgr) CreateSchedulerQueues(sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400276
Gamze Abakafee36392019-10-03 11:17:24 +0000277 log.Debugw("CreateSchedulerQueues", log.Fields{"Dir": sq.direction, "IntfID": sq.intfID,
278 "OnuID": sq.onuID, "UniID": sq.uniID, "TpID": sq.tpID, "MeterID": sq.meterID,
279 "TpInst": sq.tpInst, "flowMetadata": sq.flowMetadata})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400280
Gamze Abakafee36392019-10-03 11:17:24 +0000281 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000282 if err != nil {
283 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400284 }
285
286 /* Lets make a simple assumption that if the meter-id is present on the KV store,
287 * then the scheduler and queues configuration is applied on the OLT device
288 * in the given direction.
289 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000290
Manikkaraj kb1d51442019-07-23 10:41:02 -0400291 var SchedCfg *tp_pb.SchedulerConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000292 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400293 if err != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000294 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 -0400295 return err
296 }
297 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000298 if KvStoreMeter.MeterId == sq.meterID {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400299 log.Debug("Scheduler already created for upstream")
300 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400301 }
Gamze Abakafee36392019-10-03 11:17:24 +0000302 log.Errorw("Dynamic meter update not supported", log.Fields{"KvStoreMeterId": KvStoreMeter.MeterId, "MeterID-in-flow": sq.meterID})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000303 return errors.New("invalid-meter-id-in-flow")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400304 }
Gamze Abakafee36392019-10-03 11:17:24 +0000305 log.Debugw("Meter-does-not-exist-Creating-new", log.Fields{"MeterID": sq.meterID, "Direction": Direction})
306 if sq.direction == tp_pb.Direction_UPSTREAM {
307 SchedCfg = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
308 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
309 SchedCfg = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400310 }
311 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000312 if sq.flowMetadata != nil {
313 for _, meter := range sq.flowMetadata.Meters {
314 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400315 meterConfig = meter
316 log.Debugw("Found-meter-config-from-flowmetadata", log.Fields{"meterConfig": meterConfig})
317 break
318 }
319 }
320 } else {
321 log.Error("Flow-metadata-is-not-present-in-flow")
322 }
323 if meterConfig == nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000324 log.Errorw("Could-not-get-meterbands-from-flowMetadata", log.Fields{"flowMetadata": sq.flowMetadata,
325 "MeterID": sq.meterID})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000326 return errors.New("failed-to-get-meter-from-flowMetadata")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400327 } else if len(meterConfig.Bands) < MaxMeterBand {
Gamze Abakafee36392019-10-03 11:17:24 +0000328 log.Errorw("Invalid-number-of-bands-in-meter", log.Fields{"Bands": meterConfig.Bands, "MeterID": sq.meterID})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000329 return errors.New("invalid-number-of-bands-in-meter")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400330 }
331 cir := meterConfig.Bands[0].Rate
332 cbs := meterConfig.Bands[0].BurstSize
333 eir := meterConfig.Bands[1].Rate
334 ebs := meterConfig.Bands[1].BurstSize
335 pir := cir + eir
336 pbs := cbs + ebs
337 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
338
Gamze Abakafee36392019-10-03 11:17:24 +0000339 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Manikkaraj kb1d51442019-07-23 10:41:02 -0400340
341 log.Debugw("Sending Traffic scheduler create to device", log.Fields{"Direction": Direction, "TrafficScheds": TrafficSched})
342 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000343 IntfId: sq.intfID, OnuId: sq.onuID,
344 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400345 TrafficScheds: TrafficSched}); err != nil {
346 log.Errorw("Failed to create traffic schedulers", log.Fields{"error": err})
347 return err
348 }
349 // On receiving the CreateTrafficQueues request, the driver should create corresponding
350 // downstream queues.
Gamze Abakafee36392019-10-03 11:17:24 +0000351 trafficQueues := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400352 log.Debugw("Sending Traffic Queues create to device", log.Fields{"Direction": Direction, "TrafficQueues": trafficQueues})
353 if _, err := f.deviceHandler.Client.CreateTrafficQueues(context.Background(),
Gamze Abakafee36392019-10-03 11:17:24 +0000354 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
355 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400356 TrafficQueues: trafficQueues}); err != nil {
357 log.Errorw("Failed to create traffic queues in device", log.Fields{"error": err})
358 return err
359 }
360
salmansiddiqui7ac62132019-08-22 03:58:50 +0000361 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400362 * store the meter id on the KV store, for further reference.
363 */
Gamze Abakafee36392019-10-03 11:17:24 +0000364 if err := f.resourceMgr.UpdateMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterConfig); err != nil {
365 log.Error("Failed to update meter id for onu %d, meterid %d", sq.onuID, sq.meterID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400366 return err
367 }
368 log.Debugw("updated-meter-info into KV store successfully", log.Fields{"Direction": Direction,
369 "Meter": meterConfig})
370 return nil
371}
372
salmansiddiqui7ac62132019-08-22 03:58:50 +0000373// 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 +0000374func (f *OpenOltFlowMgr) RemoveSchedulerQueues(sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400375
376 var Direction string
377 var SchedCfg *tp_pb.SchedulerConfig
378 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000379 log.Debugw("Removing schedulers and Queues in OLT", log.Fields{"Direction": sq.direction, "IntfID": sq.intfID,
380 "OnuID": sq.onuID, "UniID": sq.uniID, "UniPort": sq.uniPort})
381 if sq.direction == tp_pb.Direction_UPSTREAM {
382 SchedCfg = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400383 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000384 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
385 SchedCfg = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400386 Direction = "downstream"
387 }
388
Gamze Abakafee36392019-10-03 11:17:24 +0000389 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400390 if err != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000391 log.Errorf("Failed to get Meter for Onu %d", sq.onuID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400392 return err
393 }
394 if KVStoreMeter == nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000395 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 -0400396 return nil
397 }
398 cir := KVStoreMeter.Bands[0].Rate
399 cbs := KVStoreMeter.Bands[0].BurstSize
400 eir := KVStoreMeter.Bands[1].Rate
401 ebs := KVStoreMeter.Bands[1].BurstSize
402 pir := cir + eir
403 pbs := cbs + ebs
404
405 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
406
Gamze Abakafee36392019-10-03 11:17:24 +0000407 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
408 TrafficQueues := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400409
410 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(context.Background(),
Gamze Abakafee36392019-10-03 11:17:24 +0000411 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
412 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400413 TrafficQueues: TrafficQueues}); err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000414 log.Errorw("Failed to remove traffic queues", log.Fields{"error": err})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400415 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400416 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000417 log.Debug("Removed traffic queues successfully")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400418 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000419 IntfId: sq.intfID, OnuId: sq.onuID,
420 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400421 TrafficScheds: TrafficSched}); err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000422 log.Errorw("failed to remove traffic schedulers", log.Fields{"error": err})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400423 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400424 }
425
salmansiddiqui7ac62132019-08-22 03:58:50 +0000426 log.Debug("Removed traffic schedulers successfully")
427
428 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400429 * delete the meter id on the KV store.
430 */
Gamze Abakafee36392019-10-03 11:17:24 +0000431 err = f.resourceMgr.RemoveMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400432 if err != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000433 log.Errorf("Failed to remove meter for onu %d, meter id %d", sq.onuID, KVStoreMeter.MeterId)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000434 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400435 }
436 log.Debugw("Removed-meter-from-KV-store successfully", log.Fields{"MeterId": KVStoreMeter.MeterId, "dir": Direction})
437 return err
438}
439
Gamze Abakafee36392019-10-03 11:17:24 +0000440// This function allocates tconts and GEM ports for an ONU
441func (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) {
442 var allocIDs []uint32
443 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530444 var gemPortIDs []uint32
Gamze Abakafee36392019-10-03 11:17:24 +0000445
446 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(intfID, onuID, uniID)
447 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400448
449 tpPath := f.getTPpath(intfID, uni, TpID)
450 // Check tech profile instance already exists for derived port name
salmansiddiqui7ac62132019-08-22 03:58:50 +0000451 techProfileInstance, err := f.techprofile[intfID].GetTPInstanceFromKVStore(TpID, tpPath)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400452 if err != nil { // This should not happen, something wrong in KV backend transaction
453 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": TpID, "path": tpPath})
Gamze Abakafee36392019-10-03 11:17:24 +0000454 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530455 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400456
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700457 log.Debug("Creating New TConts and Gem ports", log.Fields{"pon": intfID, "onu": onuID, "uni": uniID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530458
salmansiddiqui7ac62132019-08-22 03:58:50 +0000459 if techProfileInstance == nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530460 log.Info("Creating tech profile instance", log.Fields{"path": tpPath})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000461 techProfileInstance = f.techprofile[intfID].CreateTechProfInstance(TpID, uni, intfID)
462 if techProfileInstance == nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530463 log.Error("Tech-profile-instance-creation-failed")
Gamze Abakafee36392019-10-03 11:17:24 +0000464 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530465 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000466 f.resourceMgr.UpdateTechProfileIDForOnu(intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530467 } else {
468 log.Debugw("Tech-profile-instance-already-exist-for-given port-name", log.Fields{"uni": uni})
469 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400470 if UsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000471 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
472 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
473 if err := f.CreateSchedulerQueues(sq); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400474 log.Errorw("CreateSchedulerQueues Failed-upstream", log.Fields{"error": err, "meterID": UsMeterID})
Gamze Abakafee36392019-10-03 11:17:24 +0000475 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400476 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530477 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400478 if DsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000479 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
480 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
481 if err := f.CreateSchedulerQueues(sq); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400482 log.Errorw("CreateSchedulerQueues Failed-downstream", log.Fields{"error": err, "meterID": DsMeterID})
Gamze Abakafee36392019-10-03 11:17:24 +0000483 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400484 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530485 }
Gamze Abakafee36392019-10-03 11:17:24 +0000486
487 allocID := techProfileInstance.UsScheduler.AllocID
488 allocIDs = appendUnique(allocIDs, allocID)
489
490 for _, gem := range techProfileInstance.UpstreamGemPortAttributeList {
491 allgemPortIDs = appendUnique(allgemPortIDs, gem.GemportID)
492 gemPortIDs = append(gemPortIDs, gem.GemportID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400493 }
Gamze Abakafee36392019-10-03 11:17:24 +0000494
495 log.Debugw("Allocated Tcont and GEM ports", log.Fields{"allocIDs": allocIDs, "gemports": allgemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530496 // Send Tconts and GEM ports to KV store
Gamze Abakafee36392019-10-03 11:17:24 +0000497 f.storeTcontsGEMPortsIntoKVStore(intfID, onuID, uniID, allocIDs, allgemPortIDs)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000498 return allocID, gemPortIDs, techProfileInstance
manikkaraj kbf256be2019-03-25 00:13:48 +0530499}
500
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700501func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530502
503 log.Debugw("Storing allocated Tconts and GEM ports into KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700504 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "allocID": allocID, "gemPortIDs": gemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530505 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700506 if err := f.resourceMgr.UpdateAllocIdsForOnu(intfID, onuID, uniID, allocID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530507 log.Error("Errow while uploading allocID to KV store")
508 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700509 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(intfID, onuID, uniID, gemPortIDs); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530510 log.Error("Errow while uploading GEMports to KV store")
511 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700512 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(gemPortIDs, intfID, onuID, uniID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530513 log.Error("Errow while uploading gemtopon map to KV store")
514 }
515 log.Debug("Stored tconts and GEM into KV store successfully")
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400516 for _, gemPort := range gemPortIDs {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700517 f.addGemPortToOnuInfoMap(intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400518 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530519}
520
521func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000522 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530523 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000524 for _, intfID := range techRange.IntfIds {
525 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400526 tpCount++
salmansiddiqui7ac62132019-08-22 03:58:50 +0000527 log.Debugw("Init tech profile done", log.Fields{"intfID": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530528 }
529 }
530 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400531 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530532 log.Errorw("Error while populating techprofile",
Manikkaraj kb1d51442019-07-23 10:41:02 -0400533 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000534 return errors.New("error while populating techprofile mgrs")
manikkaraj kbf256be2019-03-25 00:13:48 +0530535 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400536 log.Infow("Populated techprofile for ponports successfully",
537 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
manikkaraj kbf256be2019-03-25 00:13:48 +0530538 return nil
539}
540
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700541func (f *OpenOltFlowMgr) addUpstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530542 portNo uint32, uplinkClassifier map[string]interface{},
543 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700544 allocID uint32, gemportID uint32) {
545 uplinkClassifier[PacketTagType] = SingleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530546 log.Debugw("Adding upstream data flow", log.Fields{"uplinkClassifier": uplinkClassifier, "uplinkAction": uplinkAction})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700547 f.addHSIAFlow(intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700548 Upstream, logicalFlow, allocID, gemportID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530549 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530550}
551
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700552func (f *OpenOltFlowMgr) addDownstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530553 portNo uint32, downlinkClassifier map[string]interface{},
554 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700555 allocID uint32, gemportID uint32) {
556 downlinkClassifier[PacketTagType] = DoubleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530557 log.Debugw("Adding downstream data flow", log.Fields{"downlinkClassifier": downlinkClassifier,
558 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400559 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
560 if vlan, exists := downlinkClassifier[VlanVid]; exists {
561 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700562 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Manikkaraj kb1d51442019-07-23 10:41:02 -0400563 if uint32(metadata.(uint64)) == MkUniPortNum(intfID, onuID, uniID) {
564 log.Infow("Ignoring DL trap device flow from core", log.Fields{"flow": logicalFlow})
565 return
566 }
567 }
568 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530569 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400570
Manikkaraj k884c1242019-04-11 16:26:42 +0530571 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700572 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400573 // vlan_vid is a uint32. must be type asserted as such or conversion fails
574 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530575 if ok {
576 downlinkAction[VlanVid] = dlClVid & 0xfff
577 } else {
578 log.Error("dl-classifier-vid-type-conversion-failed")
579 return
580 }
581
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700582 f.addHSIAFlow(intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700583 Downstream, logicalFlow, allocID, gemportID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530584}
585
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700586func (f *OpenOltFlowMgr) addHSIAFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +0530587 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700588 allocID uint32, gemPortID uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530589 var networkIntfID uint32
Manikkaraj k884c1242019-04-11 16:26:42 +0530590 /* One of the OLT platform (Broadcom BAL) requires that symmetric
591 flows require the same flow_id to be used across UL and DL.
592 Since HSIA flow is the only symmetric flow currently, we need to
593 re-use the flow_id across both direction. The 'flow_category'
594 takes priority over flow_cookie to find any available HSIA_FLOW
595 id for the ONU.
596 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700597 log.Debugw("Adding HSIA flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "classifier": classifier,
598 "action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530599 "logicalFlow": *logicalFlow})
Gamze Abakafee36392019-10-03 11:17:24 +0000600 var vlanPbit uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400601 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000602 vlanPbit = classifier[VlanPcp].(uint32)
603 log.Debugw("Found pbit in the flow", log.Fields{"VlanPbit": vlanPbit})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400604 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700605 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530606 flowID, err := f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530607 if err != nil {
608 log.Errorw("Flow id unavailable for HSIA flow", log.Fields{"direction": direction})
609 return
610 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700611 var classifierProto *openoltpb2.Classifier
612 var actionProto *openoltpb2.Action
Manikkaraj k884c1242019-04-11 16:26:42 +0530613 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
614 log.Error("Error in making classifier protobuf for hsia flow")
615 return
616 }
617 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
618 if actionProto = makeOpenOltActionField(action); actionProto == nil {
619 log.Errorw("Error in making action protobuf for hsia flow", log.Fields{"direction": direction})
620 return
621 }
622 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530623 networkIntfID, err = getNniIntfID(classifier, action)
624 if err != nil {
625 log.Error("Failed to get nniIntf ID")
626 return
627 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700628 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
629 OnuId: int32(onuID),
630 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000631 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530632 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700633 AllocId: int32(allocID),
634 NetworkIntfId: int32(networkIntfID),
635 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530636 Classifier: classifierProto,
637 Action: actionProto,
638 Priority: int32(logicalFlow.Priority),
639 Cookie: logicalFlow.Cookie,
640 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400641 if ok := f.addFlowToDevice(logicalFlow, &flow); ok {
Manikkaraj k884c1242019-04-11 16:26:42 +0530642 log.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530643 flowsToKVStore := f.getUpdatedFlowInfo(&flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
Manikkaraj k884c1242019-04-11 16:26:42 +0530644 if err := f.updateFlowInfoToKVStore(flow.AccessIntfId,
645 flow.OnuId,
646 flow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400647 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530648 log.Errorw("Error uploading HSIA flow into KV store", log.Fields{"flow": flow, "direction": direction, "error": err})
649 return
650 }
651 }
652}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700653func (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 +0530654
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700655 var dhcpFlow openoltpb2.Flow
656 var actionProto *openoltpb2.Action
657 var classifierProto *openoltpb2.Classifier
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530658 var flowID uint32
659 networkIntfID, err := getNniIntfID(classifier, action)
660 if err != nil {
661 log.Error("Failed to get nniIntf ID")
662 return
663 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530664
665 // Clear the action map
666 for k := range action {
667 delete(action, k)
668 }
669
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700670 action[TrapToHost] = true
671 classifier[UDPSrc] = uint32(68)
672 classifier[UDPDst] = uint32(67)
673 classifier[PacketTagType] = SingleTag
674 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530675
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700676 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530677
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530678 flowID, err = f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0 /*classifier[VLAN_PCP].(uint32)*/)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530679
680 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700681 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530682 return
683 }
684
685 log.Debugw("Creating UL DHCP flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID})
686
687 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
688 log.Error("Error in making classifier protobuf for ul flow")
689 return
690 }
691 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
692 if actionProto = makeOpenOltActionField(action); actionProto == nil {
693 log.Error("Error in making action protobuf for ul flow")
694 return
695 }
696
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700697 dhcpFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
698 OnuId: int32(onuID),
699 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530700 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700701 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700702 AllocId: int32(allocID),
703 NetworkIntfId: int32(networkIntfID),
704 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530705 Classifier: classifierProto,
706 Action: actionProto,
707 Priority: int32(logicalFlow.Priority),
708 Cookie: logicalFlow.Cookie,
709 PortNo: portNo}
710
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400711 if ok := f.addFlowToDevice(logicalFlow, &dhcpFlow); ok {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530712 log.Debug("DHCP UL flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530713 flowsToKVStore := f.getUpdatedFlowInfo(&dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530714 if err := f.updateFlowInfoToKVStore(dhcpFlow.AccessIntfId,
715 dhcpFlow.OnuId,
716 dhcpFlow.UniId,
717 dhcpFlow.FlowId, flowsToKVStore); err != nil {
718 log.Errorw("Error uploading DHCP UL flow into KV store", log.Fields{"flow": dhcpFlow, "error": err})
719 return
720 }
721 }
722
manikkaraj kbf256be2019-03-25 00:13:48 +0530723 return
724}
725
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700726// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530727func (f *OpenOltFlowMgr) addEAPOLFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, vlanID uint32, classifier map[string]interface{}, action map[string]interface{}) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700728 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 +0530729
730 uplinkClassifier := make(map[string]interface{})
731 uplinkAction := make(map[string]interface{})
732 downlinkClassifier := make(map[string]interface{})
733 downlinkAction := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700734 var upstreamFlow openoltpb2.Flow
735 var downstreamFlow openoltpb2.Flow
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530736 var networkIntfID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530737
738 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700739 uplinkClassifier[EthType] = uint32(EapEthType)
740 uplinkClassifier[PacketTagType] = SingleTag
741 uplinkClassifier[VlanVid] = vlanID
manikkaraj kbf256be2019-03-25 00:13:48 +0530742 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700743 uplinkAction[TrapToHost] = true
744 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530745 //Add Uplink EAPOL Flow
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530746 uplinkFlowID, err := f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530747 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700748 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manikkaraj k884c1242019-04-11 16:26:42 +0530749 return
manikkaraj kbf256be2019-03-25 00:13:48 +0530750 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700751 var classifierProto *openoltpb2.Classifier
752 var actionProto *openoltpb2.Action
753 log.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530754
755 if classifierProto = makeOpenOltClassifierField(uplinkClassifier); classifierProto == nil {
756 log.Error("Error in making classifier protobuf for ul flow")
757 return
758 }
759 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
760 if actionProto = makeOpenOltActionField(uplinkAction); actionProto == nil {
761 log.Error("Error in making action protobuf for ul flow")
762 return
763 }
764 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530765 networkIntfID, err = getNniIntfID(classifier, action)
766 if err != nil {
767 log.Error("Failed to get nniIntf ID")
768 return
769 }
770
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700771 upstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
772 OnuId: int32(onuID),
773 UniId: int32(uniID),
774 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700775 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700776 AllocId: int32(allocID),
777 NetworkIntfId: int32(networkIntfID),
778 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530779 Classifier: classifierProto,
780 Action: actionProto,
781 Priority: int32(logicalFlow.Priority),
782 Cookie: logicalFlow.Cookie,
783 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400784 if ok := f.addFlowToDevice(logicalFlow, &upstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530785 log.Debug("EAPOL UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400786 flowCategory := "EAPOL"
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530787 flowsToKVStore := f.getUpdatedFlowInfo(&upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
manikkaraj kbf256be2019-03-25 00:13:48 +0530788 if err := f.updateFlowInfoToKVStore(upstreamFlow.AccessIntfId,
789 upstreamFlow.OnuId,
790 upstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400791 upstreamFlow.FlowId,
792 /* lowCategory, */
793 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530794 log.Errorw("Error uploading EAPOL UL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
795 return
796 }
797 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400798 // Dummy Downstream flow due to BAL 2.6 limitation
799 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530800 /* Add Downstream EAPOL Flow, Only for first EAP flow (BAL
801 # requirement)
802 # On one of the platforms (Broadcom BAL), when same DL classifier
803 # vlan was used across multiple ONUs, eapol flow re-adds after
804 # flow delete (cases of onu reboot/disable) fails.
805 # In order to generate unique vlan, a combination of intf_id
806 # onu_id and uniId is used.
807 # uniId defaults to 0, so add 1 to it.
808 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700809 log.Debugw("Creating DL EAPOL flow with default vlan", log.Fields{"vlan": vlanID})
810 specialVlanDlFlow := 4090 - intfID*onuID*(uniID+1)
manikkaraj kbf256be2019-03-25 00:13:48 +0530811 // Assert that we do not generate invalid vlans under no condition
812 if specialVlanDlFlow <= 2 {
813 log.Fatalw("invalid-vlan-generated", log.Fields{"vlan": specialVlanDlFlow})
814 return
815 }
816 log.Debugw("specialVlanEAPOLDlFlow:", log.Fields{"dl_vlan": specialVlanDlFlow})
817 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700818 downlinkClassifier[PacketTagType] = SingleTag
Manikkaraj kb1d51442019-07-23 10:41:02 -0400819 downlinkClassifier[EthType] = uint32(EapEthType)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700820 downlinkClassifier[VlanVid] = uint32(specialVlanDlFlow)
manikkaraj kbf256be2019-03-25 00:13:48 +0530821 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700822 downlinkAction[PushVlan] = true
823 downlinkAction[VlanVid] = vlanID
824 flowStoreCookie := getFlowStoreCookie(downlinkClassifier, gemPortID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530825 downlinkFlowID, err := f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530826 if err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530827 log.Errorw("flowId unavailable for DL EAPOL",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700828 log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
manikkaraj kbf256be2019-03-25 00:13:48 +0530829 return
830 }
831 log.Debugw("Creating DL EAPOL flow",
salmansiddiqui7ac62132019-08-22 03:58:50 +0000832 log.Fields{"dl_classifier": downlinkClassifier, "dl_action": downlinkAction, "downlinkFlowID": downlinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530833 if classifierProto = makeOpenOltClassifierField(downlinkClassifier); classifierProto == nil {
834 log.Error("Error in making classifier protobuf for downlink flow")
835 return
836 }
837 if actionProto = makeOpenOltActionField(downlinkAction); actionProto == nil {
838 log.Error("Error in making action protobuf for dl flow")
839 return
840 }
841 // Downstream flow in grpc protobuf
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700842 downstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
843 OnuId: int32(onuID),
844 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000845 FlowId: downlinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700846 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700847 AllocId: int32(allocID),
848 NetworkIntfId: int32(networkIntfID),
849 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530850 Classifier: classifierProto,
851 Action: actionProto,
852 Priority: int32(logicalFlow.Priority),
853 Cookie: logicalFlow.Cookie,
854 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400855 if ok := f.addFlowToDevice(logicalFlow, &downstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530856 log.Debug("EAPOL DL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400857 flowCategory := ""
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530858 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamFlow, flowStoreCookie, flowCategory, downlinkFlowID, logicalFlow.Id)
manikkaraj kbf256be2019-03-25 00:13:48 +0530859 if err := f.updateFlowInfoToKVStore(downstreamFlow.AccessIntfId,
860 downstreamFlow.OnuId,
861 downstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400862 downstreamFlow.FlowId,
863 /* flowCategory, */
864 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530865 log.Errorw("Error uploading EAPOL DL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
866 return
867 }
868 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530869 }
870 log.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
871}
872
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700873func makeOpenOltClassifierField(classifierInfo map[string]interface{}) *openoltpb2.Classifier {
874 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -0700875
876 classifier.EthType, _ = classifierInfo[EthType].(uint32)
877 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
878 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
879 vid := vlanID & VlanvIDMask
880 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -0400881 classifier.OVid = vid
882 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530883 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700884 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
885 vid := uint32(metadata)
886 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -0400887 classifier.IVid = vid
888 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530889 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700890 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400891 if vlanPcp == 0 {
892 classifier.OPbits = VlanPCPMask
893 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700894 classifier.OPbits = vlanPcp & VlanPCPMask
Manikkaraj kb1d51442019-07-23 10:41:02 -0400895 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530896 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700897 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
898 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
899 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
900 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
901 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
902 classifier.PktTagType = pktTagType
903
904 switch pktTagType {
905 case SingleTag:
906 case DoubleTag:
907 case Untagged:
908 default:
manikkaraj kbf256be2019-03-25 00:13:48 +0530909 log.Error("Invalid tag type in classifier") // should not hit
910 return nil
911 }
912 }
913 return &classifier
914}
915
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700916func makeOpenOltActionField(actionInfo map[string]interface{}) *openoltpb2.Action {
917 var actionCmd openoltpb2.ActionCmd
918 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +0530919 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700920 if _, ok := actionInfo[PopVlan]; ok {
921 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530922 action.Cmd.RemoveOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700923 } else if _, ok := actionInfo[PushVlan]; ok {
924 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530925 action.Cmd.AddOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700926 } else if _, ok := actionInfo[TrapToHost]; ok {
927 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +0530928 } else {
929 log.Errorw("Invalid-action-field", log.Fields{"action": actionInfo})
930 return nil
931 }
932 return &action
933}
934
Manikkaraj kb1d51442019-07-23 10:41:02 -0400935func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uni string, TpID uint32) string {
936 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530937}
938
Gamze Abakafee36392019-10-03 11:17:24 +0000939// DeleteTechProfileInstances removes the tech profile instances from persistent storage
940func (f *OpenOltFlowMgr) DeleteTechProfileInstances(intfID uint32, onuID uint32, uniID uint32, sn string) error {
941 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(intfID, onuID, uniID)
Devmalya Paul495b94a2019-08-27 19:42:00 -0400942 uniPortName := fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +0000943 for _, tpID := range tpIDList {
944 if err := f.DeleteTechProfileInstance(intfID, onuID, uniID, uniPortName, tpID); err != nil {
945 log.Debugw("Failed-to-delete-tp-instance-from-kv-store", log.Fields{"tp-id": tpID, "uni-port-name": uniPortName})
946 return err
947 }
948 }
949 return nil
950}
951
952// DeleteTechProfileInstance removes the tech profile instance from persistent storage
953func (f *OpenOltFlowMgr) DeleteTechProfileInstance(intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
954 if uniPortName == "" {
955 uniPortName = fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
956 }
Devmalya Paul495b94a2019-08-27 19:42:00 -0400957 if err := f.techprofile[intfID].DeleteTechProfileInstance(tpID, uniPortName); err != nil {
958 log.Debugw("Failed-to-delete-tp-instance-from-kv-store", log.Fields{"tp-id": tpID, "uni-port-name": uniPortName})
959 return err
960 }
961 return nil
962}
963
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700964func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530965 if len(classifier) == 0 { // should never happen
966 log.Error("Invalid classfier object")
967 return 0
968 }
969 var jsonData []byte
970 var flowString string
971 var err error
972 // TODO: Do we need to marshall ??
973 if jsonData, err = json.Marshal(classifier); err != nil {
974 log.Error("Failed to encode classifier")
975 return 0
976 }
977 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700978 if gemPortID != 0 {
979 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +0530980 }
981 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700982 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +0530983 hash := big.NewInt(0)
984 hash.SetBytes(h.Sum(nil))
985 return hash.Uint64()
986}
987
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530988func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openoltpb2.Flow, flowStoreCookie uint64, flowCategory string, deviceFlowID uint32, logicalFlowID uint64) *[]rsrcMgr.FlowInfo {
989 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700990 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400991 /* For flows which trap out of the NNI, the AccessIntfId is invalid
992 (set to -1). In such cases, we need to refer to the NetworkIntfId .
993 */
994 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700995 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400996 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700997 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400998 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700999 // Get existing flows matching flowid for given subscriber from KV store
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301000 existingFlows := f.resourceMgr.GetFlowIDInfo(intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001001 if existingFlows != nil {
1002 log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001003 //for _, f := range *existingFlows {
1004 // flows = append(flows, f)
1005 //}
1006 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001007 }
1008 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 +05301009 return &flows
1010}
1011
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001012//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
1013// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
1014// var intfId uint32
1015// /* For flows which trap out of the NNI, the AccessIntfId is invalid
1016// (set to -1). In such cases, we need to refer to the NetworkIntfId .
1017// */
1018// if flow.AccessIntfId != -1 {
1019// intfId = uint32(flow.AccessIntfId)
1020// } else {
1021// intfId = uint32(flow.NetworkIntfId)
1022// }
1023// // Get existing flows matching flowid for given subscriber from KV store
1024// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
1025// if existingFlows != nil {
1026// log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
1027// for _, f := range *existingFlows {
1028// flows = append(flows, f)
1029// }
1030// }
1031// log.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
1032// return &flows
1033//}
1034
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001035func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
manikkaraj k17652a72019-05-06 09:06:36 -04001036 log.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001037 if err := f.resourceMgr.UpdateFlowIDInfo(intfID, onuID, uniID, flowID, flows); err != nil {
manikkaraj k17652a72019-05-06 09:06:36 -04001038 log.Debug("Error while Storing flow into KV store")
1039 return err
1040 }
1041 log.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +05301042 return nil
1043}
1044
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001045func (f *OpenOltFlowMgr) addFlowToDevice(logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) bool {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001046
1047 var intfID uint32
1048 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1049 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1050 */
1051 if deviceFlow.AccessIntfId != -1 {
1052 intfID = uint32(deviceFlow.AccessIntfId)
1053 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001054 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001055 intfID = uint32(deviceFlow.NetworkIntfId)
1056 }
1057
manikkaraj kbf256be2019-03-25 00:13:48 +05301058 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1059 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001060
1061 st, _ := status.FromError(err)
1062 if st.Code() == codes.AlreadyExists {
Gamze Abakafee36392019-10-03 11:17:24 +00001063 log.Debug("Flow already exists", log.Fields{"err": err, "deviceFlow": deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301064 return false
1065 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001066
1067 if err != nil {
1068 log.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": deviceFlow})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001069 f.resourceMgr.FreeFlowID(intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001070 return false
1071 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001072 f.registerFlow(logicalFlow, deviceFlow)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301073 log.Debugw("Flow added to device successfully ", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001074 return true
1075}
1076
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001077func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) bool {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001078 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1079 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1080 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001081 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
1082 log.Warnw("Can not remove flow from device since it's unreachable", log.Fields{"err": err, "deviceFlow": deviceFlow})
1083 //Assume the flow is removed
1084 return true
1085 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001086 log.Errorw("Failed to Remove flow from device", log.Fields{"err": err, "deviceFlow": deviceFlow})
1087 return false
serkant.uluderya245caba2019-09-24 23:15:29 -07001088
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001089 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001090 log.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301091 return true
1092}
1093
1094/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1095 //update core flows_proxy : flows_proxy.update('/', flows)
1096}
1097
1098func generateStoredId(flowId uint32, direction string)uint32{
1099
David K. Bainbridge82efc492019-09-04 09:57:11 -07001100 if direction == Upstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301101 log.Debug("Upstream flow shifting flowid")
1102 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001103 }else if direction == Downstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301104 log.Debug("Downstream flow not shifting flowid")
1105 return flowId
1106 }else{
1107 log.Errorw("Unrecognized direction",log.Fields{"direction": direction})
1108 return flowId
1109 }
1110}
1111
1112*/
1113
Humera Kouser94d7a842019-08-25 19:04:32 -04001114func (f *OpenOltFlowMgr) addLLDPFlow(flow *ofp.OfpFlowStats, portNo uint32) {
1115
1116 classifierInfo := make(map[string]interface{})
1117 actionInfo := make(map[string]interface{})
1118
1119 classifierInfo[EthType] = uint32(LldpEthType)
1120 classifierInfo[PacketTagType] = Untagged
1121 actionInfo[TrapToHost] = true
1122
1123 // LLDP flow is installed to trap LLDP packets on the NNI port.
1124 // We manage flow_id resource pool on per PON port basis.
1125 // Since this situation is tricky, as a hack, we pass the NNI port
1126 // index (network_intf_id) as PON port Index for the flow_id resource
1127 // pool. Also, there is no ONU Id available for trapping LLDP packets
1128 // on NNI port, use onu_id as -1 (invalid)
1129 // ****************** CAVEAT *******************
1130 // This logic works if the NNI Port Id falls within the same valid
1131 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1132 // we need to have a re-look at this.
1133 // *********************************************
1134
1135 var onuID = -1
1136 var uniID = -1
1137 var gemPortID = -1
1138
1139 var networkInterfaceID = IntfIDFromNniPortNum(portNo)
1140 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301141 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Humera Kouser94d7a842019-08-25 19:04:32 -04001142 log.Debug("Flow-exists--not-re-adding")
1143 return
1144 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301145 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001146
1147 if err != nil {
1148 log.Errorw("Flow id unavailable for LLDP traponNNI flow", log.Fields{"error": err})
1149 return
1150 }
1151 var classifierProto *openoltpb2.Classifier
1152 var actionProto *openoltpb2.Action
1153 if classifierProto = makeOpenOltClassifierField(classifierInfo); classifierProto == nil {
1154 log.Error("Error in making classifier protobuf for LLDP trap on nni flow")
1155 return
1156 }
1157 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1158 if actionProto = makeOpenOltActionField(actionInfo); actionProto == nil {
1159 log.Error("Error in making action protobuf for LLDP trap on nni flow")
1160 return
1161 }
1162 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
1163
1164 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1165 OnuId: int32(onuID), // OnuId not required
1166 UniId: int32(uniID), // UniId not used
1167 FlowId: flowID,
1168 FlowType: Downstream,
1169 NetworkIntfId: int32(networkInterfaceID),
1170 GemportId: int32(gemPortID),
1171 Classifier: classifierProto,
1172 Action: actionProto,
1173 Priority: int32(flow.Priority),
1174 Cookie: flow.Cookie,
1175 PortNo: portNo}
1176 if ok := f.addFlowToDevice(flow, &downstreamflow); ok {
1177 log.Debug("LLDP trap on NNI flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301178 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID, flow.Id)
Humera Kouser94d7a842019-08-25 19:04:32 -04001179 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1180 int32(onuID),
1181 int32(uniID),
1182 flowID, flowsToKVStore); err != nil {
1183 log.Errorw("Error uploading LLDP flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1184 }
1185 }
1186 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301187}
1188
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301189func getUniPortPath(intfID uint32, onuID int32, uniID int32) string {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001190 return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1191}
1192
1193//getOnuChildDevice to fetch onu
1194func (f *OpenOltFlowMgr) getOnuChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
1195 log.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
1196 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
1197 onuDevice := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301198 if onuDevice == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001199 log.Errorw("onu not found", log.Fields{"intfId": parentPortNo, "onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301200 return nil, errors.New("onu not found")
manikkaraj kbf256be2019-03-25 00:13:48 +05301201 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301202 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1203 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301204}
1205
1206func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001207 log.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301208 return nil
1209}
1210
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001211func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
1212 log.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301213}
1214
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001215func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001216 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001217 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001218 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001219 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001220}
1221
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301222// FindAndRemoveFlow finds the flow from kv store and makes a call to remove the flow from device
1223// returns the flows and gemport the flow is associated with.
1224func (f *OpenOltFlowMgr) FindAndRemoveFlow(flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32, flowDirection string) ([]rsrcMgr.FlowInfo, int32, uint32) {
1225
1226 var updatedFlows []rsrcMgr.FlowInfo
1227 var gemPortID int32
1228 var flowID uint32
1229
1230 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(Intf, onuID, uniID)
1231FlowFound:
1232 for _, flowID = range flowIds {
1233 flowInfo := f.resourceMgr.GetFlowIDInfo(Intf, onuID, uniID, flowID)
1234 if flowInfo == nil {
1235 log.Debugw("No FlowInfo found found in KV store",
1236 log.Fields{"Intf": Intf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1237 return nil, 0, flowID
1238 }
1239 updatedFlows = nil
1240 for _, flow := range *flowInfo {
1241 updatedFlows = append(updatedFlows, flow)
1242 }
1243
1244 for i, storedFlow := range updatedFlows {
1245 if flowDirection == storedFlow.Flow.FlowType && flow.Id == storedFlow.LogicalFlowID {
1246 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: flowDirection}
1247 if ok := f.removeFlowFromDevice(&removeFlowMessage); ok {
1248 log.Debug("Flow removed from device successfully")
1249 //Remove the Flow from FlowInfo
1250 log.Debugw("Removing flow to be deleted", log.Fields{"flow": storedFlow})
1251 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1252 gemPortID = storedFlow.Flow.GemportId
1253 break FlowFound
1254 } else {
1255 log.Error("Failed to remove flow from device")
1256 return nil, 0, flowID
1257 }
1258 }
1259 }
1260 }
1261 return updatedFlows, gemPortID, flowID
1262}
1263
1264func (f *OpenOltFlowMgr) clearFlowFromResourceManager(flow *ofp.OfpFlowStats, flowDirection string) {
1265
1266 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowDirection": flowDirection, "flow": *flow})
1267 var updatedFlows []rsrcMgr.FlowInfo
1268 var flowID uint32
1269 var onuID, uniID int32
1270 classifierInfo := make(map[string]interface{})
1271
1272 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001273 if err != nil {
1274 log.Error(err)
1275 return
1276 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301277 onuID = int32(onu)
1278 uniID = int32(uni)
Gamze Abakafee36392019-10-03 11:17:24 +00001279 var gemPortID int32
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001280
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301281 for _, field := range flows.GetOfbFields(flow) {
1282 if field.Type == flows.IP_PROTO {
1283 classifierInfo[IPProto] = field.GetIpProto()
1284 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001285 }
1286 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301287 log.Debugw("Extracted access info from flow to be deleted",
1288 log.Fields{"ponIntf": Intf, "onuID": onuID, "uniID": uniID})
1289
1290 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1291 onuID = -1
1292 uniID = -1
1293 log.Debug("Trap on nni flow set oni, uni to -1")
1294 Intf = IntfIDFromNniPortNum(inPort)
1295 }
1296 updatedFlows, gemPortID, flowID = f.FindAndRemoveFlow(flow, Intf, onuID, uniID, flowDirection)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001297
Gamze Abakafee36392019-10-03 11:17:24 +00001298 tpID := getTpIDFromFlow(flow)
1299
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001300 if len(updatedFlows) >= 0 {
1301 // There are still flows referencing the same flow_id.
1302 // So the flow should not be freed yet.
1303 // For ex: Case of HSIA where same flow is shared
1304 // between DS and US.
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301305 f.updateFlowInfoToKVStore(int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001306 if len(updatedFlows) == 0 {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301307 log.Debugw("Releasing flow Id to resource manager", log.Fields{"Intf": Intf, "onuId": onuID, "uniId": uniID, "flowId": flowID})
1308 f.resourceMgr.FreeFlowID(Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001309
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301310 uni := getUniPortPath(Intf, onuID, uniID)
1311 tpPath := f.getTPpath(Intf, uni, tpID)
Gamze Abakafee36392019-10-03 11:17:24 +00001312 log.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301313 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(tpID, tpPath)
Gamze Abakafee36392019-10-03 11:17:24 +00001314 if err != nil { // This should not happen, something wrong in KV backend transaction
1315 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": 20, "path": tpPath})
1316 return
1317 }
1318 if techprofileInst == nil {
1319 log.Errorw("Tech-profile-instance-does-not-exist-in-KV Store", log.Fields{"tpPath": tpPath})
1320 return
1321 }
1322
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301323 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00001324 if f.isGemPortUsedByAnotherFlow(gemPK) {
1325 flowIDs := f.flowsUsedByGemPort[gemPK]
1326 for i, flowIDinMap := range flowIDs {
1327 if flowIDinMap == flowID {
1328 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
1329 f.flowsUsedByGemPort[gemPK] = flowIDs
1330 break
1331 }
1332 }
1333 log.Debugw("Gem port id is still used by other flows", log.Fields{"gemPortID": gemPortID, "usedByFlows": flowIDs})
1334 return
1335 }
1336
1337 log.Debugf("Gem port id %d is not used by another flow - releasing the gem port", gemPortID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301338 f.resourceMgr.RemoveGemPortIDForOnu(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001339 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1340 // But it is anyway eventually removed later when the TechProfile is freed, so not a big issue for now.
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301341 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(uint32(gemPortID), Intf)
Gamze Abakafee36392019-10-03 11:17:24 +00001342 f.onuIdsLock.Lock()
1343 delete(f.flowsUsedByGemPort, gemPK)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301344 //delete(f.onuGemPortIds, gemPK)
1345 f.resourceMgr.FreeGemPortID(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001346 f.onuIdsLock.Unlock()
1347
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301348 ok, _ := f.isTechProfileUsedByAnotherGem(Intf, uint32(onuID), uint32(uniID), techprofileInst, uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001349 if !ok {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301350 f.resourceMgr.RemoveTechProfileIDForOnu(Intf, uint32(onuID), uint32(uniID), tpID)
1351 f.RemoveSchedulerQueues(schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1352 f.RemoveSchedulerQueues(schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1353 f.DeleteTechProfileInstance(Intf, uint32(onuID), uint32(uniID), "", tpID)
1354 f.resourceMgr.FreeAllocID(Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
Gamze Abakafee36392019-10-03 11:17:24 +00001355 // TODO: Send a "Delete TechProfile" message to ONU to do its own clean up on ONU OMCI stack
1356 }
1357 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001358 }
1359}
1360
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001361//RemoveFlow removes the flow from the device
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001362func (f *OpenOltFlowMgr) RemoveFlow(flow *ofp.OfpFlowStats) {
1363 log.Debugw("Removing Flow", log.Fields{"flow": flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301364 var direction string
1365 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001366
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301367 for _, action := range flows.GetActions(flow) {
1368 if action.Type == flows.OUTPUT {
1369 if out := action.GetOutput(); out != nil {
1370 actionInfo[Output] = out.GetPort()
1371 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
1372 } else {
1373 log.Error("Invalid output port in action")
1374 return
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001375 }
1376 }
1377 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301378 if IsUpstream(actionInfo[Output].(uint32)) {
1379 direction = Upstream
1380 } else {
1381 direction = Downstream
1382 }
1383
1384 f.clearFlowFromResourceManager(flow, direction) //TODO: Take care of the limitations
1385
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001386 return
1387}
1388
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001389// AddFlow add flow to device
Manikkaraj kb1d51442019-07-23 10:41:02 -04001390func (f *OpenOltFlowMgr) AddFlow(flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001391 classifierInfo := make(map[string]interface{})
1392 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001393 var UsMeterID uint32
1394 var DsMeterID uint32
1395
1396 log.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001397 formulateClassifierInfoFromFlow(classifierInfo, flow)
1398
1399 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
1400 if err != nil {
1401 // Error logging is already done in the called function
1402 // So just return in case of error
1403 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301404 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001405
manikkaraj k17652a72019-05-06 09:06:36 -04001406 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00001407 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
1408 if err != nil {
1409 // error if any, already logged in the called function
1410 return
manikkaraj k17652a72019-05-06 09:06:36 -04001411 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001412
David K. Bainbridge82efc492019-09-04 09:57:11 -07001413 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[Output]})
1414 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00001415
Humera Kouser94d7a842019-08-25 19:04:32 -04001416 if ethType, ok := classifierInfo[EthType]; ok {
1417 if ethType.(uint32) == LldpEthType {
1418 log.Info("Adding LLDP flow")
1419 f.addLLDPFlow(flow, portNo)
1420 return
1421 }
1422 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001423 if ipProto, ok := classifierInfo[IPProto]; ok {
1424 if ipProto.(uint32) == IPProtoDhcp {
1425 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001426 if udpSrc.(uint32) == uint32(67) {
1427 log.Debug("trap-dhcp-from-nni-flow")
1428 f.addDHCPTrapFlowOnNNI(flow, classifierInfo, portNo)
1429 return
1430 }
1431 }
1432 }
1433 }
A R Karthick1f85b802019-10-11 05:06:05 +00001434
1435 f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301436 f.resourceMgr.AddUniPortToOnuInfo(intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00001437
Gamze Abakafee36392019-10-03 11:17:24 +00001438 TpID := getTpIDFromFlow(flow)
1439
salmansiddiqui7ac62132019-08-22 03:58:50 +00001440 log.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001441 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07001442 UsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001443 log.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
1444 } else {
Scott Baker355d1742019-10-24 10:57:52 -07001445 DsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001446 log.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
1447
1448 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001449 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001450}
1451
1452//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04001453func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001454
1455 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301456 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001457 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301458 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301459 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301460 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04001461
Manikkaraj kb1d51442019-07-23 10:41:02 -04001462 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001463 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
manikkaraj k17652a72019-05-06 09:06:36 -04001464 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
1465 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1466 tpDownloadMsg,
1467 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
1468 f.deviceHandler.deviceType,
1469 onuDevice.Type,
1470 onuDevice.Id,
1471 onuDevice.ProxyAddress.DeviceId, "")
1472 if sendErr != nil {
1473 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1474 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1475 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1476 return sendErr
1477 }
1478 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05301479 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301480}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001481
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301482//UpdateOnuInfo function adds onu info to cache and kvstore
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001483func (f *OpenOltFlowMgr) UpdateOnuInfo(intfID uint32, onuID uint32, serialNum string) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301484
1485 f.lockCache.Lock()
1486 defer f.lockCache.Unlock()
1487 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
1488 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
1489 if err := f.resourceMgr.AddOnuInfo(intfID, onu); err != nil {
1490 log.Errorw("failed to add onu info", log.Fields{"onu": onu})
1491 return
1492 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001493 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
1494}
1495
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301496//addGemPortToOnuInfoMap function adds GEMport to ONU map
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001497func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(intfID uint32, onuID uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301498 f.lockCache.Lock()
1499 defer f.lockCache.Unlock()
1500 onugem := f.onuGemInfo[intfID]
1501 // update the gem to the local cache as well as to kv strore
1502 for idx, onu := range onugem {
1503 if onu.OnuID == onuID {
1504 // check if gem already exists , else update the cache and kvstore
1505 for _, gem := range onu.GemPorts {
1506 if gem == gemPort {
1507 log.Debugw("Gem already in cache, no need to update cache and kv store",
1508 log.Fields{"gem": gemPort})
1509 return
1510 }
1511 }
1512 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
1513 f.onuGemInfo[intfID] = onugem
1514 }
1515 }
1516 err := f.resourceMgr.AddGemToOnuGemInfo(intfID, onuID, gemPort)
1517 if err != nil {
1518 log.Errorw("Failed to add gem to onu", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001519 return
1520 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001521}
1522
1523// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001524
1525//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
1526func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301527
1528 f.lockCache.Lock()
1529 defer f.lockCache.Unlock()
1530
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001531 log.Debugw("Getting ONU ID from GEM port and PON port", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPortId": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301532 // get onuid from the onugem info cache
1533 onugem := f.onuGemInfo[intfID]
1534 for _, onu := range onugem {
1535 for _, gem := range onu.GemPorts {
1536 if gem == gemPortID {
1537 return onu.OnuID, nil
1538 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001539 }
1540 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001541 log.Errorw("onuid is not found", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPort": gemPortID})
1542 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 -04001543}
1544
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001545//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
1546func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001547 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001548 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001549 var err error
1550
1551 if packetIn.IntfType == "pon" {
1552 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001553 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001554 log.Errorw("Unable to get ONU ID from GEM/PON port", log.Fields{"pon port": packetIn.IntfId, "gemport": packetIn.GemportId})
1555 return logicalPortNum, err
1556 }
1557 if packetIn.PortNo != 0 {
1558 logicalPortNum = packetIn.PortNo
1559 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001560 uniID := uint32(0) // FIXME - multi-uni support
1561 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001562 }
1563 // Store the gem port through which the packet_in came. Use the same gem port for packet_out
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301564 f.UpdateGemPortForPktIn(packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001565 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001566 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001567 }
1568 log.Debugw("Retrieved logicalport from packet-in", log.Fields{"logicalPortNum": logicalPortNum, "IntfType": packetIn.IntfType})
1569 return logicalPortNum, nil
1570}
1571
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001572//GetPacketOutGemPortID returns gemPortId
1573func (f *OpenOltFlowMgr) GetPacketOutGemPortID(intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
1574 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001575 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301576
1577 f.lockCache.Lock()
1578 defer f.lockCache.Unlock()
1579 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum}
1580
1581 gemPortID, ok := f.packetInGemPort[pktInkey]
1582 if ok {
1583 log.Debugw("Found gemport for pktin key", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1584 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001585 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301586 //If gem is not found in cache try to get it from kv store, if found in kv store, update the cache and return.
1587 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(intfID, onuID, portNum)
1588 if err == nil {
1589 if gemPortID != 0 {
1590 f.packetInGemPort[pktInkey] = gemPortID
1591 log.Debugw("Found gem port from kv store and updating cache with gemport",
1592 log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1593 return gemPortID, nil
1594 }
1595 }
1596 log.Errorw("Failed to get gemport", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1597 return uint32(0), err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001598}
1599
Manikkaraj kb1d51442019-07-23 10:41:02 -04001600func installFlowOnAllGemports(
1601 f1 func(intfId uint32, onuId uint32, uniId uint32,
1602 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
1603 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32),
1604 f2 func(intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301605 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
1606 classifier map[string]interface{}, action map[string]interface{}),
Manikkaraj kb1d51442019-07-23 10:41:02 -04001607 args map[string]uint32,
1608 classifier map[string]interface{}, action map[string]interface{},
1609 logicalFlow *ofp.OfpFlowStats,
1610 gemPorts []uint32,
1611 FlowType string,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001612 vlanID ...uint32) {
1613 log.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
1614 for _, gemPortID := range gemPorts {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001615 if FlowType == HsiaFlow || FlowType == DhcpFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001616 f1(args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001617 } else if FlowType == EapolFlow {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301618 f2(args["intfId"], args["onuId"], args["uniId"], args["portNo"], logicalFlow, args["allocId"], gemPortID, vlanID[0], classifier, action)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001619 } else {
1620 log.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
1621 return
1622 }
1623 }
1624}
1625
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001626func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
1627 log.Debug("Adding trap-dhcp-of-nni-flow")
1628 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001629 classifier[PacketTagType] = DoubleTag
1630 action[TrapToHost] = true
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301631 var err error
1632 var networkInterfaceID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001633 /* We manage flowId resource pool on per PON port basis.
1634 Since this situation is tricky, as a hack, we pass the NNI port
1635 index (network_intf_id) as PON port Index for the flowId resource
1636 pool. Also, there is no ONU Id available for trapping DHCP packets
1637 on NNI port, use onu_id as -1 (invalid)
1638 ****************** CAVEAT *******************
1639 This logic works if the NNI Port Id falls within the same valid
1640 range of PON Port Ids. If this doesn't work for some OLT Vendor
1641 we need to have a re-look at this.
1642 *********************************************
1643 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001644 onuID := -1
1645 uniID := -1
1646 gemPortID := -1
1647 allocID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301648 networkInterfaceID, err = getNniIntfID(classifier, action)
1649 if err != nil {
1650 log.Error("Failed to get nniIntf ID")
1651 return
1652 }
1653
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001654 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301655 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001656 log.Debug("Flow-exists--not-re-adding")
1657 return
1658 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301659 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001660 if err != nil {
1661 log.Errorw("Flow id unavailable for DHCP traponNNI flow", log.Fields{"error": err})
1662 return
1663 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001664 var classifierProto *openoltpb2.Classifier
1665 var actionProto *openoltpb2.Action
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001666 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
1667 log.Error("Error in making classifier protobuf for dhcp trap on nni flow")
1668 return
1669 }
1670 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1671 if actionProto = makeOpenOltActionField(action); actionProto == nil {
1672 log.Error("Error in making action protobuf for dhcp trap on nni flow")
1673 return
1674 }
1675 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001676 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1677 OnuId: int32(onuID), // OnuId not required
1678 UniId: int32(uniID), // UniId not used
1679 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001680 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001681 AllocId: int32(allocID), // AllocId not used
1682 NetworkIntfId: int32(networkInterfaceID),
1683 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001684 Classifier: classifierProto,
1685 Action: actionProto,
1686 Priority: int32(logicalFlow.Priority),
1687 Cookie: logicalFlow.Cookie,
1688 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001689 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001690 log.Debug("DHCP trap on NNI flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301691 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001692 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1693 int32(onuID),
1694 int32(uniID),
1695 flowID, flowsToKVStore); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001696 log.Errorw("Error uploading DHCP DL flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1697 }
1698 }
1699 return
1700}
salmansiddiqui7ac62132019-08-22 03:58:50 +00001701
1702func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
1703 if MeterID == 0 { // This should never happen
1704 log.Error("Invalid meter id")
1705 return "", errors.New("invalid meter id")
1706 }
1707 if Dir == tp_pb.Direction_UPSTREAM {
1708 return "upstream", nil
1709 } else if Dir == tp_pb.Direction_DOWNSTREAM {
1710 return "downstream", nil
1711 }
1712 return "", nil
1713}
1714
1715func (f *OpenOltFlowMgr) checkAndAddFlow(args map[string]uint32, classifierInfo map[string]interface{},
Gamze Abakafee36392019-10-03 11:17:24 +00001716 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst *tp.TechProfile, gemPorts []uint32,
1717 TpID uint32, uni string) {
1718 var gemPort uint32
1719 intfID := args[IntfID]
1720 onuID := args[OnuID]
1721 uniID := args[UniID]
1722 portNo := args[PortNo]
1723 allocID := TpInst.UsScheduler.AllocID
salmansiddiqui7ac62132019-08-22 03:58:50 +00001724 if ipProto, ok := classifierInfo[IPProto]; ok {
1725 if ipProto.(uint32) == IPProtoDhcp {
1726 log.Info("Adding DHCP flow")
1727 if pcp, ok := classifierInfo[VlanPcp]; ok {
1728 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1729 tp_pb.Direction_UPSTREAM,
1730 pcp.(uint32))
1731 //Adding DHCP upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001732 f.addDHCPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001733 } else {
1734 //Adding DHCP upstream flow to all gemports
1735 installFlowOnAllGemports(f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, DhcpFlow)
1736 }
1737
1738 } else if ipProto == IgmpProto {
1739 log.Info("igmp flow add ignored, not implemented yet")
1740 return
1741 } else {
1742 log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
1743 return
1744 }
1745 } else if ethType, ok := classifierInfo[EthType]; ok {
1746 if ethType.(uint32) == EapEthType {
1747 log.Info("Adding EAPOL flow")
1748 var vlanID uint32
1749 if val, ok := classifierInfo[VlanVid]; ok {
1750 vlanID = (val.(uint32)) & VlanvIDMask
1751 } else {
1752 vlanID = DefaultMgmtVlan
1753 }
1754 if pcp, ok := classifierInfo[VlanPcp]; ok {
1755 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1756 tp_pb.Direction_UPSTREAM,
1757 pcp.(uint32))
1758
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301759 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID, gemPort, vlanID, classifierInfo, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001760 } else {
1761 installFlowOnAllGemports(nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, EapolFlow, vlanID)
1762 }
1763 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001764 } else if _, ok := actionInfo[PushVlan]; ok {
1765 log.Info("Adding upstream data rule")
1766 if pcp, ok := classifierInfo[VlanPcp]; ok {
1767 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1768 tp_pb.Direction_UPSTREAM,
1769 pcp.(uint32))
1770 //Adding HSIA upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001771 f.addUpstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001772 } else {
1773 //Adding HSIA upstream flow to all gemports
1774 installFlowOnAllGemports(f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1775 }
1776 } else if _, ok := actionInfo[PopVlan]; ok {
1777 log.Info("Adding Downstream data rule")
1778 if pcp, ok := classifierInfo[VlanPcp]; ok {
1779 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05001780 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001781 pcp.(uint32))
1782 //Adding HSIA downstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001783 f.addDownstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001784 } else {
1785 //Adding HSIA downstream flow to all gemports
1786 installFlowOnAllGemports(f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1787 }
1788 } else {
1789 log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
1790 return
1791 }
1792 // Send Techprofile download event to child device in go routine as it takes time
1793 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, TpID)
1794}
1795
Gamze Abakafee36392019-10-03 11:17:24 +00001796func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
1797 flowIDList := f.flowsUsedByGemPort[gemPK]
1798 if len(flowIDList) > 1 {
1799 return true
1800 }
1801 return false
1802}
1803
1804func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ponIntf uint32, onuID uint32, uniID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
1805 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ponIntf, onuID, uniID)
1806 tpGemPorts := tpInst.UpstreamGemPortAttributeList
1807 for _, currentGemPort := range currentGemPorts {
1808 for _, tpGemPort := range tpGemPorts {
1809 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
1810 return true, currentGemPort
1811 }
1812 }
1813 }
1814 return false, 0
1815}
1816
salmansiddiqui7ac62132019-08-22 03:58:50 +00001817func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07001818 for _, field := range flows.GetOfbFields(flow) {
1819 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001820 classifierInfo[EthType] = field.GetEthType()
1821 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001822 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001823 classifierInfo[IPProto] = field.GetIpProto()
1824 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001825 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001826 classifierInfo[InPort] = field.GetPort()
1827 log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001828 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05301829 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
salmansiddiqui7ac62132019-08-22 03:58:50 +00001830 log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001831 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001832 classifierInfo[VlanPcp] = field.GetVlanPcp()
1833 log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001834 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001835 classifierInfo[UDPDst] = field.GetUdpDst()
1836 log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001837 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001838 classifierInfo[UDPSrc] = field.GetUdpSrc()
1839 log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001840 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001841 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
1842 log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001843 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001844 classifierInfo[Ipv4Src] = field.GetIpv4Src()
1845 log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001846 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001847 classifierInfo[Metadata] = field.GetTableMetadata()
1848 log.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07001849 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001850 classifierInfo[TunnelID] = field.GetTunnelId()
1851 log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
1852 } else {
1853 log.Errorw("Un supported field type", log.Fields{"type": field.Type})
1854 return
1855 }
1856 }
1857}
1858
1859func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07001860 for _, action := range flows.GetActions(flow) {
1861 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001862 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001863 actionInfo[Output] = out.GetPort()
1864 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001865 } else {
1866 log.Error("Invalid output port in action")
1867 return errors.New("invalid output port in action")
1868 }
Scott Baker355d1742019-10-24 10:57:52 -07001869 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001870 actionInfo[PopVlan] = true
1871 log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001872 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001873 if out := action.GetPush(); out != nil {
1874 if tpid := out.GetEthertype(); tpid != 0x8100 {
1875 log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
1876 } else {
1877 actionInfo[PushVlan] = true
1878 actionInfo[TPID] = tpid
1879 log.Debugw("action-type-push-vlan",
1880 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
1881 }
1882 }
Scott Baker355d1742019-10-24 10:57:52 -07001883 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001884 if out := action.GetSetField(); out != nil {
1885 if field := out.GetField(); field != nil {
1886 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
1887 log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
1888 return errors.New("invalid openflow class")
1889 }
1890 /*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
1891 if ofbField := field.GetOfbField(); ofbField != nil {
1892 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
1893 if vlan := ofbField.GetVlanVid(); vlan != 0 {
1894 actionInfo[VlanVid] = vlan & 0xfff
1895 log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
1896 } else {
1897 log.Error("No Invalid vlan id in set vlan-vid action")
1898 }
1899 } else {
1900 log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
1901 }
1902 }
1903 }
1904 }
1905 } else {
1906 log.Errorw("Un supported action type", log.Fields{"type": action.Type})
1907 return errors.New("un supported action type")
1908 }
1909 }
1910 return nil
1911}
1912
1913func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001914 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001915 log.Debug("Controller bound trap flows, getting inport from tunnelid")
1916 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
1917 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001918 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001919 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07001920 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 +00001921 } else {
1922 log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1923 return errors.New("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1924 }
1925 }
1926 } else {
1927 log.Debug("Non-Controller flows, getting uniport from tunnelid")
1928 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07001929 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001930 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001931 actionInfo[Output] = uniPort
1932 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 +00001933 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001934 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 +00001935 return errors.New("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid")
1936 }
1937 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
1938 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001939 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001940 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07001941 log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[Output].(uint32),
1942 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001943 } else {
1944 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 -07001945 "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001946 return errors.New("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid")
1947 }
1948 }
1949 }
1950 return nil
1951}
Gamze Abakafee36392019-10-03 11:17:24 +00001952
1953func getTpIDFromFlow(flow *ofp.OfpFlowStats) uint32 {
1954 /* Metadata 8 bytes:
1955 Most Significant 2 Bytes = Inner VLAN
1956 Next 2 Bytes = Tech Profile ID(TPID)
1957 Least Significant 4 Bytes = Port ID
1958 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
1959 subscriber related flows.
1960 */
1961 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
1962 if metadata == 0 {
1963 log.Error("Metadata is not present in flow which is mandatory")
1964 return 0
1965 }
1966 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
1967 return uint32(TpID)
1968}
1969
1970func appendUnique(slice []uint32, item uint32) []uint32 {
1971 for _, sliceElement := range slice {
1972 if sliceElement == item {
1973 return slice
1974 }
1975 }
1976 return append(slice, item)
1977}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301978
1979// getNniIntfID gets nni intf id from the flow classifier/action
1980func getNniIntfID(classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
1981
1982 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
1983 if portType == voltha.Port_PON_OLT {
1984 intfID := IntfIDFromNniPortNum(action[Output].(uint32))
1985 log.Debugw("output Nni IntfID is", log.Fields{"intfid": intfID})
1986 return intfID, nil
1987 } else if portType == voltha.Port_ETHERNET_NNI {
1988 intfID := IntfIDFromNniPortNum(classifier[InPort].(uint32))
1989 log.Debugw("input Nni IntfID is", log.Fields{"intfid": intfID})
1990 return intfID, nil
1991 }
1992 return uint32(0), nil
1993}
1994
1995// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
1996func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32) {
1997 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort}
1998
1999 f.lockCache.Lock()
2000 defer f.lockCache.Unlock()
2001 _, ok := f.packetInGemPort[pktInkey]
2002 if ok {
2003 log.Debugw("pktin key found in cache , no need to update kv as we are assuming both will be in sync",
2004 log.Fields{"pktinkey": pktInkey, "gem": gemPort})
2005 } else {
2006 f.packetInGemPort[pktInkey] = gemPort
2007
2008 f.resourceMgr.UpdateGemPortForPktIn(pktInkey, gemPort)
2009 log.Debugw("pktin key not found in local cache updating cache and kv store", log.Fields{"pktinkey": pktInkey, "gem": gemPort})
2010 }
2011 return
2012}
2013
2014// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
2015func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(intfID uint32, onuID uint32, portNum uint32) {
2016
2017 f.lockCache.Lock()
2018 defer f.lockCache.Unlock()
2019 onugem := f.onuGemInfo[intfID]
2020 for idx, onu := range onugem {
2021 if onu.OnuID == onuID {
2022 for _, uni := range onu.UniPorts {
2023 if uni == portNum {
2024 log.Debugw("uni already in cache, no need to update cache and kv store",
2025 log.Fields{"uni": portNum})
2026 return
2027 }
2028 }
2029 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
2030 f.onuGemInfo[intfID] = onugem
2031 }
2032 }
2033 f.resourceMgr.AddUniPortToOnuInfo(intfID, onuID, portNum)
2034}