blob: 4064cfe622e5339e9daa5bd5931d5d3eb876b67f [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 Laxmeshwarb7300fe2019-11-13 03:38:33 +05301222//clearResources clears pon resources in kv store and the device
1223func (f *OpenOltFlowMgr) clearResources(flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
1224 gemPortID int32, flowID uint32, flowDirection string,
1225 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001226
Gamze Abakafee36392019-10-03 11:17:24 +00001227 tpID := getTpIDFromFlow(flow)
1228
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001229 if len(updatedFlows) >= 0 {
1230 // There are still flows referencing the same flow_id.
1231 // So the flow should not be freed yet.
1232 // For ex: Case of HSIA where same flow is shared
1233 // between DS and US.
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301234 f.updateFlowInfoToKVStore(int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001235 if len(updatedFlows) == 0 {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301236 log.Debugw("Releasing flow Id to resource manager", log.Fields{"Intf": Intf, "onuId": onuID, "uniId": uniID, "flowId": flowID})
1237 f.resourceMgr.FreeFlowID(Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001238
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301239 uni := getUniPortPath(Intf, onuID, uniID)
1240 tpPath := f.getTPpath(Intf, uni, tpID)
Gamze Abakafee36392019-10-03 11:17:24 +00001241 log.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301242 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(tpID, tpPath)
Gamze Abakafee36392019-10-03 11:17:24 +00001243 if err != nil { // This should not happen, something wrong in KV backend transaction
1244 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": 20, "path": tpPath})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301245 return err
Gamze Abakafee36392019-10-03 11:17:24 +00001246 }
1247 if techprofileInst == nil {
1248 log.Errorw("Tech-profile-instance-does-not-exist-in-KV Store", log.Fields{"tpPath": tpPath})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301249 return err
Gamze Abakafee36392019-10-03 11:17:24 +00001250 }
1251
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301252 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00001253 if f.isGemPortUsedByAnotherFlow(gemPK) {
1254 flowIDs := f.flowsUsedByGemPort[gemPK]
1255 for i, flowIDinMap := range flowIDs {
1256 if flowIDinMap == flowID {
1257 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
1258 f.flowsUsedByGemPort[gemPK] = flowIDs
1259 break
1260 }
1261 }
1262 log.Debugw("Gem port id is still used by other flows", log.Fields{"gemPortID": gemPortID, "usedByFlows": flowIDs})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301263 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00001264 }
Gamze Abakafee36392019-10-03 11:17:24 +00001265 log.Debugf("Gem port id %d is not used by another flow - releasing the gem port", gemPortID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301266 f.resourceMgr.RemoveGemPortIDForOnu(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001267 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1268 // 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 +05301269 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(uint32(gemPortID), Intf)
Gamze Abakafee36392019-10-03 11:17:24 +00001270 f.onuIdsLock.Lock()
1271 delete(f.flowsUsedByGemPort, gemPK)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301272 //delete(f.onuGemPortIds, gemPK)
1273 f.resourceMgr.FreeGemPortID(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001274 f.onuIdsLock.Unlock()
1275
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301276 ok, _ := f.isTechProfileUsedByAnotherGem(Intf, uint32(onuID), uint32(uniID), techprofileInst, uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001277 if !ok {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301278 f.resourceMgr.RemoveTechProfileIDForOnu(Intf, uint32(onuID), uint32(uniID), tpID)
1279 f.RemoveSchedulerQueues(schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1280 f.RemoveSchedulerQueues(schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1281 f.DeleteTechProfileInstance(Intf, uint32(onuID), uint32(uniID), "", tpID)
1282 f.resourceMgr.FreeAllocID(Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
Gamze Abakafee36392019-10-03 11:17:24 +00001283 // TODO: Send a "Delete TechProfile" message to ONU to do its own clean up on ONU OMCI stack
1284 }
1285 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001286 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301287 return nil
1288}
1289
1290func (f *OpenOltFlowMgr) clearFlowFromResourceManager(flow *ofp.OfpFlowStats, flowDirection string) {
1291
1292 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowDirection": flowDirection, "flow": *flow})
1293 var updatedFlows []rsrcMgr.FlowInfo
1294 var flowID uint32
1295 var onuID, uniID int32
1296 classifierInfo := make(map[string]interface{})
1297
1298 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
1299 if err != nil {
1300 log.Error(err)
1301 return
1302 }
1303 onuID = int32(onu)
1304 uniID = int32(uni)
1305
1306 for _, field := range flows.GetOfbFields(flow) {
1307 if field.Type == flows.IP_PROTO {
1308 classifierInfo[IPProto] = field.GetIpProto()
1309 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
1310 }
1311 }
1312 log.Debugw("Extracted access info from flow to be deleted",
1313 log.Fields{"ponIntf": Intf, "onuID": onuID, "uniID": uniID})
1314
1315 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1316 onuID = -1
1317 uniID = -1
1318 log.Debug("Trap on nni flow set oni, uni to -1")
1319 Intf = IntfIDFromNniPortNum(inPort)
1320 }
1321 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(Intf, onuID, uniID)
1322 for _, flowID = range flowIds {
1323 flowInfo := f.resourceMgr.GetFlowIDInfo(Intf, onuID, uniID, flowID)
1324 if flowInfo == nil {
1325 log.Debugw("No FlowInfo found found in KV store",
1326 log.Fields{"Intf": Intf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1327 return
1328 }
1329 updatedFlows = nil
1330 for _, flow := range *flowInfo {
1331 updatedFlows = append(updatedFlows, flow)
1332 }
1333
1334 for i, storedFlow := range updatedFlows {
1335 if flow.Id == storedFlow.LogicalFlowID {
1336 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
1337 log.Debugw("Flow to be deleted", log.Fields{"flow": storedFlow})
1338 if ok := f.removeFlowFromDevice(&removeFlowMessage); ok {
1339 log.Debug("Flow removed from device successfully")
1340 //Remove the Flow from FlowInfo
1341 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1342 err = f.clearResources(flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
1343 flowID, flowDirection, portNum, updatedFlows)
1344 if err != nil {
1345 log.Error("Failed to clear resources for flow", log.Fields{"flow": storedFlow})
1346 return
1347 }
1348 } else {
1349 log.Error("Failed to remove flow from device")
1350 return
1351 }
1352 }
1353 }
1354 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001355}
1356
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001357//RemoveFlow removes the flow from the device
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001358func (f *OpenOltFlowMgr) RemoveFlow(flow *ofp.OfpFlowStats) {
1359 log.Debugw("Removing Flow", log.Fields{"flow": flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301360 var direction string
1361 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001362
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301363 for _, action := range flows.GetActions(flow) {
1364 if action.Type == flows.OUTPUT {
1365 if out := action.GetOutput(); out != nil {
1366 actionInfo[Output] = out.GetPort()
1367 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
1368 } else {
1369 log.Error("Invalid output port in action")
1370 return
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001371 }
1372 }
1373 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301374 if IsUpstream(actionInfo[Output].(uint32)) {
1375 direction = Upstream
1376 } else {
1377 direction = Downstream
1378 }
1379
1380 f.clearFlowFromResourceManager(flow, direction) //TODO: Take care of the limitations
1381
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001382 return
1383}
1384
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001385// AddFlow add flow to device
Manikkaraj kb1d51442019-07-23 10:41:02 -04001386func (f *OpenOltFlowMgr) AddFlow(flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001387 classifierInfo := make(map[string]interface{})
1388 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001389 var UsMeterID uint32
1390 var DsMeterID uint32
1391
1392 log.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001393 formulateClassifierInfoFromFlow(classifierInfo, flow)
1394
1395 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
1396 if err != nil {
1397 // Error logging is already done in the called function
1398 // So just return in case of error
1399 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301400 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001401
manikkaraj k17652a72019-05-06 09:06:36 -04001402 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00001403 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
1404 if err != nil {
1405 // error if any, already logged in the called function
1406 return
manikkaraj k17652a72019-05-06 09:06:36 -04001407 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001408
David K. Bainbridge82efc492019-09-04 09:57:11 -07001409 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[Output]})
1410 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00001411
Humera Kouser94d7a842019-08-25 19:04:32 -04001412 if ethType, ok := classifierInfo[EthType]; ok {
1413 if ethType.(uint32) == LldpEthType {
1414 log.Info("Adding LLDP flow")
1415 f.addLLDPFlow(flow, portNo)
1416 return
1417 }
1418 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001419 if ipProto, ok := classifierInfo[IPProto]; ok {
1420 if ipProto.(uint32) == IPProtoDhcp {
1421 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001422 if udpSrc.(uint32) == uint32(67) {
1423 log.Debug("trap-dhcp-from-nni-flow")
1424 f.addDHCPTrapFlowOnNNI(flow, classifierInfo, portNo)
1425 return
1426 }
1427 }
1428 }
1429 }
A R Karthick1f85b802019-10-11 05:06:05 +00001430
1431 f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301432 f.resourceMgr.AddUniPortToOnuInfo(intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00001433
Gamze Abakafee36392019-10-03 11:17:24 +00001434 TpID := getTpIDFromFlow(flow)
1435
salmansiddiqui7ac62132019-08-22 03:58:50 +00001436 log.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001437 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07001438 UsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001439 log.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
1440 } else {
Scott Baker355d1742019-10-24 10:57:52 -07001441 DsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001442 log.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
1443
1444 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001445 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001446}
1447
1448//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04001449func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001450
1451 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301452 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001453 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301454 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301455 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301456 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04001457
Manikkaraj kb1d51442019-07-23 10:41:02 -04001458 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001459 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
manikkaraj k17652a72019-05-06 09:06:36 -04001460 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
1461 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1462 tpDownloadMsg,
1463 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
1464 f.deviceHandler.deviceType,
1465 onuDevice.Type,
1466 onuDevice.Id,
1467 onuDevice.ProxyAddress.DeviceId, "")
1468 if sendErr != nil {
1469 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1470 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1471 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1472 return sendErr
1473 }
1474 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05301475 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301476}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001477
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301478//UpdateOnuInfo function adds onu info to cache and kvstore
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001479func (f *OpenOltFlowMgr) UpdateOnuInfo(intfID uint32, onuID uint32, serialNum string) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301480
1481 f.lockCache.Lock()
1482 defer f.lockCache.Unlock()
1483 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
1484 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
1485 if err := f.resourceMgr.AddOnuInfo(intfID, onu); err != nil {
1486 log.Errorw("failed to add onu info", log.Fields{"onu": onu})
1487 return
1488 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001489 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
1490}
1491
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301492//addGemPortToOnuInfoMap function adds GEMport to ONU map
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001493func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(intfID uint32, onuID uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301494 f.lockCache.Lock()
1495 defer f.lockCache.Unlock()
1496 onugem := f.onuGemInfo[intfID]
1497 // update the gem to the local cache as well as to kv strore
1498 for idx, onu := range onugem {
1499 if onu.OnuID == onuID {
1500 // check if gem already exists , else update the cache and kvstore
1501 for _, gem := range onu.GemPorts {
1502 if gem == gemPort {
1503 log.Debugw("Gem already in cache, no need to update cache and kv store",
1504 log.Fields{"gem": gemPort})
1505 return
1506 }
1507 }
1508 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
1509 f.onuGemInfo[intfID] = onugem
1510 }
1511 }
1512 err := f.resourceMgr.AddGemToOnuGemInfo(intfID, onuID, gemPort)
1513 if err != nil {
1514 log.Errorw("Failed to add gem to onu", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001515 return
1516 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001517}
1518
1519// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001520
1521//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
1522func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301523
1524 f.lockCache.Lock()
1525 defer f.lockCache.Unlock()
1526
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001527 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 +05301528 // get onuid from the onugem info cache
1529 onugem := f.onuGemInfo[intfID]
1530 for _, onu := range onugem {
1531 for _, gem := range onu.GemPorts {
1532 if gem == gemPortID {
1533 return onu.OnuID, nil
1534 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001535 }
1536 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001537 log.Errorw("onuid is not found", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPort": gemPortID})
1538 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 -04001539}
1540
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001541//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
1542func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001543 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001544 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001545 var err error
1546
1547 if packetIn.IntfType == "pon" {
1548 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001549 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001550 log.Errorw("Unable to get ONU ID from GEM/PON port", log.Fields{"pon port": packetIn.IntfId, "gemport": packetIn.GemportId})
1551 return logicalPortNum, err
1552 }
1553 if packetIn.PortNo != 0 {
1554 logicalPortNum = packetIn.PortNo
1555 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001556 uniID := uint32(0) // FIXME - multi-uni support
1557 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001558 }
1559 // 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 +05301560 f.UpdateGemPortForPktIn(packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001561 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001562 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001563 }
1564 log.Debugw("Retrieved logicalport from packet-in", log.Fields{"logicalPortNum": logicalPortNum, "IntfType": packetIn.IntfType})
1565 return logicalPortNum, nil
1566}
1567
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001568//GetPacketOutGemPortID returns gemPortId
1569func (f *OpenOltFlowMgr) GetPacketOutGemPortID(intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
1570 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001571 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301572
1573 f.lockCache.Lock()
1574 defer f.lockCache.Unlock()
1575 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum}
1576
1577 gemPortID, ok := f.packetInGemPort[pktInkey]
1578 if ok {
1579 log.Debugw("Found gemport for pktin key", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1580 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001581 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301582 //If gem is not found in cache try to get it from kv store, if found in kv store, update the cache and return.
1583 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(intfID, onuID, portNum)
1584 if err == nil {
1585 if gemPortID != 0 {
1586 f.packetInGemPort[pktInkey] = gemPortID
1587 log.Debugw("Found gem port from kv store and updating cache with gemport",
1588 log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1589 return gemPortID, nil
1590 }
1591 }
1592 log.Errorw("Failed to get gemport", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1593 return uint32(0), err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001594}
1595
Manikkaraj kb1d51442019-07-23 10:41:02 -04001596func installFlowOnAllGemports(
1597 f1 func(intfId uint32, onuId uint32, uniId uint32,
1598 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
1599 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32),
1600 f2 func(intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301601 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
1602 classifier map[string]interface{}, action map[string]interface{}),
Manikkaraj kb1d51442019-07-23 10:41:02 -04001603 args map[string]uint32,
1604 classifier map[string]interface{}, action map[string]interface{},
1605 logicalFlow *ofp.OfpFlowStats,
1606 gemPorts []uint32,
1607 FlowType string,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001608 vlanID ...uint32) {
1609 log.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
1610 for _, gemPortID := range gemPorts {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001611 if FlowType == HsiaFlow || FlowType == DhcpFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001612 f1(args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001613 } else if FlowType == EapolFlow {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301614 f2(args["intfId"], args["onuId"], args["uniId"], args["portNo"], logicalFlow, args["allocId"], gemPortID, vlanID[0], classifier, action)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001615 } else {
1616 log.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
1617 return
1618 }
1619 }
1620}
1621
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001622func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
1623 log.Debug("Adding trap-dhcp-of-nni-flow")
1624 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001625 classifier[PacketTagType] = DoubleTag
1626 action[TrapToHost] = true
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301627 var err error
1628 var networkInterfaceID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001629 /* We manage flowId resource pool on per PON port basis.
1630 Since this situation is tricky, as a hack, we pass the NNI port
1631 index (network_intf_id) as PON port Index for the flowId resource
1632 pool. Also, there is no ONU Id available for trapping DHCP packets
1633 on NNI port, use onu_id as -1 (invalid)
1634 ****************** CAVEAT *******************
1635 This logic works if the NNI Port Id falls within the same valid
1636 range of PON Port Ids. If this doesn't work for some OLT Vendor
1637 we need to have a re-look at this.
1638 *********************************************
1639 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001640 onuID := -1
1641 uniID := -1
1642 gemPortID := -1
1643 allocID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301644 networkInterfaceID, err = getNniIntfID(classifier, action)
1645 if err != nil {
1646 log.Error("Failed to get nniIntf ID")
1647 return
1648 }
1649
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001650 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301651 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001652 log.Debug("Flow-exists--not-re-adding")
1653 return
1654 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301655 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001656 if err != nil {
1657 log.Errorw("Flow id unavailable for DHCP traponNNI flow", log.Fields{"error": err})
1658 return
1659 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001660 var classifierProto *openoltpb2.Classifier
1661 var actionProto *openoltpb2.Action
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001662 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
1663 log.Error("Error in making classifier protobuf for dhcp trap on nni flow")
1664 return
1665 }
1666 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1667 if actionProto = makeOpenOltActionField(action); actionProto == nil {
1668 log.Error("Error in making action protobuf for dhcp trap on nni flow")
1669 return
1670 }
1671 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001672 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1673 OnuId: int32(onuID), // OnuId not required
1674 UniId: int32(uniID), // UniId not used
1675 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001676 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001677 AllocId: int32(allocID), // AllocId not used
1678 NetworkIntfId: int32(networkInterfaceID),
1679 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001680 Classifier: classifierProto,
1681 Action: actionProto,
1682 Priority: int32(logicalFlow.Priority),
1683 Cookie: logicalFlow.Cookie,
1684 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001685 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001686 log.Debug("DHCP trap on NNI flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301687 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001688 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1689 int32(onuID),
1690 int32(uniID),
1691 flowID, flowsToKVStore); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001692 log.Errorw("Error uploading DHCP DL flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1693 }
1694 }
1695 return
1696}
salmansiddiqui7ac62132019-08-22 03:58:50 +00001697
1698func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
1699 if MeterID == 0 { // This should never happen
1700 log.Error("Invalid meter id")
1701 return "", errors.New("invalid meter id")
1702 }
1703 if Dir == tp_pb.Direction_UPSTREAM {
1704 return "upstream", nil
1705 } else if Dir == tp_pb.Direction_DOWNSTREAM {
1706 return "downstream", nil
1707 }
1708 return "", nil
1709}
1710
1711func (f *OpenOltFlowMgr) checkAndAddFlow(args map[string]uint32, classifierInfo map[string]interface{},
Gamze Abakafee36392019-10-03 11:17:24 +00001712 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst *tp.TechProfile, gemPorts []uint32,
1713 TpID uint32, uni string) {
1714 var gemPort uint32
1715 intfID := args[IntfID]
1716 onuID := args[OnuID]
1717 uniID := args[UniID]
1718 portNo := args[PortNo]
1719 allocID := TpInst.UsScheduler.AllocID
salmansiddiqui7ac62132019-08-22 03:58:50 +00001720 if ipProto, ok := classifierInfo[IPProto]; ok {
1721 if ipProto.(uint32) == IPProtoDhcp {
1722 log.Info("Adding DHCP flow")
1723 if pcp, ok := classifierInfo[VlanPcp]; ok {
1724 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1725 tp_pb.Direction_UPSTREAM,
1726 pcp.(uint32))
1727 //Adding DHCP upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001728 f.addDHCPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001729 } else {
1730 //Adding DHCP upstream flow to all gemports
1731 installFlowOnAllGemports(f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, DhcpFlow)
1732 }
1733
1734 } else if ipProto == IgmpProto {
1735 log.Info("igmp flow add ignored, not implemented yet")
1736 return
1737 } else {
1738 log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
1739 return
1740 }
1741 } else if ethType, ok := classifierInfo[EthType]; ok {
1742 if ethType.(uint32) == EapEthType {
1743 log.Info("Adding EAPOL flow")
1744 var vlanID uint32
1745 if val, ok := classifierInfo[VlanVid]; ok {
1746 vlanID = (val.(uint32)) & VlanvIDMask
1747 } else {
1748 vlanID = DefaultMgmtVlan
1749 }
1750 if pcp, ok := classifierInfo[VlanPcp]; ok {
1751 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1752 tp_pb.Direction_UPSTREAM,
1753 pcp.(uint32))
1754
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301755 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID, gemPort, vlanID, classifierInfo, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001756 } else {
1757 installFlowOnAllGemports(nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, EapolFlow, vlanID)
1758 }
1759 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001760 } else if _, ok := actionInfo[PushVlan]; ok {
1761 log.Info("Adding upstream data rule")
1762 if pcp, ok := classifierInfo[VlanPcp]; ok {
1763 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1764 tp_pb.Direction_UPSTREAM,
1765 pcp.(uint32))
1766 //Adding HSIA upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001767 f.addUpstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001768 } else {
1769 //Adding HSIA upstream flow to all gemports
1770 installFlowOnAllGemports(f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1771 }
1772 } else if _, ok := actionInfo[PopVlan]; ok {
1773 log.Info("Adding Downstream data rule")
1774 if pcp, ok := classifierInfo[VlanPcp]; ok {
1775 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05001776 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001777 pcp.(uint32))
1778 //Adding HSIA downstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001779 f.addDownstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001780 } else {
1781 //Adding HSIA downstream flow to all gemports
1782 installFlowOnAllGemports(f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1783 }
1784 } else {
1785 log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
1786 return
1787 }
1788 // Send Techprofile download event to child device in go routine as it takes time
1789 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, TpID)
1790}
1791
Gamze Abakafee36392019-10-03 11:17:24 +00001792func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
1793 flowIDList := f.flowsUsedByGemPort[gemPK]
1794 if len(flowIDList) > 1 {
1795 return true
1796 }
1797 return false
1798}
1799
1800func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ponIntf uint32, onuID uint32, uniID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
1801 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ponIntf, onuID, uniID)
1802 tpGemPorts := tpInst.UpstreamGemPortAttributeList
1803 for _, currentGemPort := range currentGemPorts {
1804 for _, tpGemPort := range tpGemPorts {
1805 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
1806 return true, currentGemPort
1807 }
1808 }
1809 }
1810 return false, 0
1811}
1812
salmansiddiqui7ac62132019-08-22 03:58:50 +00001813func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07001814 for _, field := range flows.GetOfbFields(flow) {
1815 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001816 classifierInfo[EthType] = field.GetEthType()
1817 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001818 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001819 classifierInfo[IPProto] = field.GetIpProto()
1820 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001821 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001822 classifierInfo[InPort] = field.GetPort()
1823 log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001824 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05301825 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
salmansiddiqui7ac62132019-08-22 03:58:50 +00001826 log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001827 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001828 classifierInfo[VlanPcp] = field.GetVlanPcp()
1829 log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001830 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001831 classifierInfo[UDPDst] = field.GetUdpDst()
1832 log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001833 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001834 classifierInfo[UDPSrc] = field.GetUdpSrc()
1835 log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001836 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001837 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
1838 log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001839 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001840 classifierInfo[Ipv4Src] = field.GetIpv4Src()
1841 log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001842 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001843 classifierInfo[Metadata] = field.GetTableMetadata()
1844 log.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07001845 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001846 classifierInfo[TunnelID] = field.GetTunnelId()
1847 log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
1848 } else {
1849 log.Errorw("Un supported field type", log.Fields{"type": field.Type})
1850 return
1851 }
1852 }
1853}
1854
1855func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07001856 for _, action := range flows.GetActions(flow) {
1857 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001858 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001859 actionInfo[Output] = out.GetPort()
1860 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001861 } else {
1862 log.Error("Invalid output port in action")
1863 return errors.New("invalid output port in action")
1864 }
Scott Baker355d1742019-10-24 10:57:52 -07001865 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001866 actionInfo[PopVlan] = true
1867 log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001868 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001869 if out := action.GetPush(); out != nil {
1870 if tpid := out.GetEthertype(); tpid != 0x8100 {
1871 log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
1872 } else {
1873 actionInfo[PushVlan] = true
1874 actionInfo[TPID] = tpid
1875 log.Debugw("action-type-push-vlan",
1876 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
1877 }
1878 }
Scott Baker355d1742019-10-24 10:57:52 -07001879 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001880 if out := action.GetSetField(); out != nil {
1881 if field := out.GetField(); field != nil {
1882 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
1883 log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
1884 return errors.New("invalid openflow class")
1885 }
1886 /*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
1887 if ofbField := field.GetOfbField(); ofbField != nil {
1888 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
1889 if vlan := ofbField.GetVlanVid(); vlan != 0 {
1890 actionInfo[VlanVid] = vlan & 0xfff
1891 log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
1892 } else {
1893 log.Error("No Invalid vlan id in set vlan-vid action")
1894 }
1895 } else {
1896 log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
1897 }
1898 }
1899 }
1900 }
1901 } else {
1902 log.Errorw("Un supported action type", log.Fields{"type": action.Type})
1903 return errors.New("un supported action type")
1904 }
1905 }
1906 return nil
1907}
1908
1909func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001910 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001911 log.Debug("Controller bound trap flows, getting inport from tunnelid")
1912 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
1913 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001914 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001915 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07001916 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 +00001917 } else {
1918 log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1919 return errors.New("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1920 }
1921 }
1922 } else {
1923 log.Debug("Non-Controller flows, getting uniport from tunnelid")
1924 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07001925 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001926 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001927 actionInfo[Output] = uniPort
1928 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 +00001929 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001930 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 +00001931 return errors.New("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid")
1932 }
1933 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
1934 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001935 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001936 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07001937 log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[Output].(uint32),
1938 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001939 } else {
1940 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 -07001941 "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001942 return errors.New("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid")
1943 }
1944 }
1945 }
1946 return nil
1947}
Gamze Abakafee36392019-10-03 11:17:24 +00001948
1949func getTpIDFromFlow(flow *ofp.OfpFlowStats) uint32 {
1950 /* Metadata 8 bytes:
1951 Most Significant 2 Bytes = Inner VLAN
1952 Next 2 Bytes = Tech Profile ID(TPID)
1953 Least Significant 4 Bytes = Port ID
1954 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
1955 subscriber related flows.
1956 */
1957 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
1958 if metadata == 0 {
1959 log.Error("Metadata is not present in flow which is mandatory")
1960 return 0
1961 }
1962 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
1963 return uint32(TpID)
1964}
1965
1966func appendUnique(slice []uint32, item uint32) []uint32 {
1967 for _, sliceElement := range slice {
1968 if sliceElement == item {
1969 return slice
1970 }
1971 }
1972 return append(slice, item)
1973}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301974
1975// getNniIntfID gets nni intf id from the flow classifier/action
1976func getNniIntfID(classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
1977
1978 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
1979 if portType == voltha.Port_PON_OLT {
1980 intfID := IntfIDFromNniPortNum(action[Output].(uint32))
1981 log.Debugw("output Nni IntfID is", log.Fields{"intfid": intfID})
1982 return intfID, nil
1983 } else if portType == voltha.Port_ETHERNET_NNI {
1984 intfID := IntfIDFromNniPortNum(classifier[InPort].(uint32))
1985 log.Debugw("input Nni IntfID is", log.Fields{"intfid": intfID})
1986 return intfID, nil
1987 }
1988 return uint32(0), nil
1989}
1990
1991// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
1992func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32) {
1993 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort}
1994
1995 f.lockCache.Lock()
1996 defer f.lockCache.Unlock()
1997 _, ok := f.packetInGemPort[pktInkey]
1998 if ok {
1999 log.Debugw("pktin key found in cache , no need to update kv as we are assuming both will be in sync",
2000 log.Fields{"pktinkey": pktInkey, "gem": gemPort})
2001 } else {
2002 f.packetInGemPort[pktInkey] = gemPort
2003
2004 f.resourceMgr.UpdateGemPortForPktIn(pktInkey, gemPort)
2005 log.Debugw("pktin key not found in local cache updating cache and kv store", log.Fields{"pktinkey": pktInkey, "gem": gemPort})
2006 }
2007 return
2008}
2009
2010// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
2011func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(intfID uint32, onuID uint32, portNum uint32) {
2012
2013 f.lockCache.Lock()
2014 defer f.lockCache.Unlock()
2015 onugem := f.onuGemInfo[intfID]
2016 for idx, onu := range onugem {
2017 if onu.OnuID == onuID {
2018 for _, uni := range onu.UniPorts {
2019 if uni == portNum {
2020 log.Debugw("uni already in cache, no need to update cache and kv store",
2021 log.Fields{"uni": portNum})
2022 return
2023 }
2024 }
2025 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
2026 f.onuGemInfo[intfID] = onugem
2027 }
2028 }
2029 f.resourceMgr.AddUniPortToOnuInfo(intfID, onuID, portNum)
2030}