blob: 8ee2a114858dd06f59adee8be888f8a7716a5b7f [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"
Matteo Scandolo6056e822019-11-13 14:05:29 -080023 "encoding/hex"
manikkaraj kbf256be2019-03-25 00:13:48 +053024 "encoding/json"
25 "errors"
26 "fmt"
Manikkaraj kb1d51442019-07-23 10:41:02 -040027 "math/big"
William Kurkian740a09c2019-10-23 17:07:38 -040028 "sync"
Manikkaraj kb1d51442019-07-23 10:41:02 -040029
Scott Baker51290152019-10-24 14:23:20 -070030 "github.com/opencord/voltha-lib-go/v2/pkg/flows"
31 "github.com/opencord/voltha-lib-go/v2/pkg/log"
32 tp "github.com/opencord/voltha-lib-go/v2/pkg/techprofile"
Manikkaraj k884c1242019-04-11 16:26:42 +053033 rsrcMgr "github.com/opencord/voltha-openolt-adapter/adaptercore/resourcemanager"
Scott Bakerc6e54cb2019-11-04 09:31:25 -080034 "github.com/opencord/voltha-protos/v2/go/common"
35 ic "github.com/opencord/voltha-protos/v2/go/inter_container"
36 ofp "github.com/opencord/voltha-protos/v2/go/openflow_13"
37 openoltpb2 "github.com/opencord/voltha-protos/v2/go/openolt"
38 tp_pb "github.com/opencord/voltha-protos/v2/go/tech_profile"
39 "github.com/opencord/voltha-protos/v2/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040040
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -040041 //deepcopy "github.com/getlantern/deepcopy"
Daniele Rossi22db98e2019-07-11 11:50:00 +000042 "google.golang.org/grpc/codes"
43 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053044)
45
46const (
47 // Flow categories
manikkaraj kbf256be2019-03-25 00:13:48 +053048
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070049 //HsiaFlow flow category
50 HsiaFlow = "HSIA_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053051
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070052 //EapolFlow flow category
53 EapolFlow = "EAPOL_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053054
Manikkaraj kb1d51442019-07-23 10:41:02 -040055 //DhcpFlow flow category
56 DhcpFlow = "DHCP_FLOW"
57
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070058 //IPProtoDhcp flow category
59 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053060
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070061 //IPProtoIgmp flow category
62 IPProtoIgmp = 2
63
64 //EapEthType eapethtype value
65 EapEthType = 0x888e
66 //LldpEthType lldp ethtype value
67 LldpEthType = 0x88cc
68
69 //IgmpProto proto value
70 IgmpProto = 2
manikkaraj kbf256be2019-03-25 00:13:48 +053071
72 //FIXME - see also BRDCM_DEFAULT_VLAN in broadcom_onu.py
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070073
Humera Kouser94d7a842019-08-25 19:04:32 -040074 //ReservedVlan Transparent Vlan
David K. Bainbridge82efc492019-09-04 09:57:11 -070075 ReservedVlan = 4095
Harsh Awasthiea45af72019-08-26 02:39:00 -040076
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070077 //DefaultMgmtVlan default vlan value
78 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053079
manikkaraj kbf256be2019-03-25 00:13:48 +053080 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070081
David K. Bainbridge82efc492019-09-04 09:57:11 -070082 //Upstream constant
83 Upstream = "upstream"
84 //Downstream constant
85 Downstream = "downstream"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070086 //PacketTagType constant
87 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070088 //Untagged constant
89 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070090 //SingleTag constant
91 SingleTag = "single_tag"
92 //DoubleTag constant
93 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053094
95 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070096
97 //EthType constant
98 EthType = "eth_type"
99 //TPID constant
100 TPID = "tpid"
101 //IPProto constant
102 IPProto = "ip_proto"
103 //InPort constant
104 InPort = "in_port"
105 //VlanVid constant
106 VlanVid = "vlan_vid"
107 //VlanPcp constant
108 VlanPcp = "vlan_pcp"
109
110 //UDPDst constant
111 UDPDst = "udp_dst"
112 //UDPSrc constant
113 UDPSrc = "udp_src"
114 //Ipv4Dst constant
115 Ipv4Dst = "ipv4_dst"
116 //Ipv4Src constant
117 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700118 //Metadata constant
119 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700120 //TunnelID constant
121 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700122 //Output constant
123 Output = "output"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700124 // Actions
125
126 //PopVlan constant
127 PopVlan = "pop_vlan"
128 //PushVlan constant
129 PushVlan = "push_vlan"
130 //TrapToHost constant
131 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400132 //MaxMeterBand constant
133 MaxMeterBand = 2
134 //VlanPCPMask contant
135 VlanPCPMask = 0xFF
136 //VlanvIDMask constant
137 VlanvIDMask = 0xFFF
138 //MaxPonPorts constant
139 MaxPonPorts = 16
Gamze Abakafee36392019-10-03 11:17:24 +0000140 //IntfID constant
141 IntfID = "intfId"
142 //OnuID constant
143 OnuID = "onuId"
144 //UniID constant
145 UniID = "uniId"
146 //PortNo constant
147 PortNo = "portNo"
148 //AllocID constant
149 AllocID = "allocId"
manikkaraj kbf256be2019-03-25 00:13:48 +0530150)
151
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400152type gemPortKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700153 intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400154 gemPort uint32
155}
156
Gamze Abakafee36392019-10-03 11:17:24 +0000157type schedQueue struct {
158 direction tp_pb.Direction
159 intfID uint32
160 onuID uint32
161 uniID uint32
162 tpID uint32
163 uniPort uint32
164 tpInst *tp.TechProfile
165 meterID uint32
166 flowMetadata *voltha.FlowMetadata
167}
168
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700169//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530170type OpenOltFlowMgr struct {
Gamze Abakafee36392019-10-03 11:17:24 +0000171 techprofile []tp.TechProfileIf
172 deviceHandler *DeviceHandler
173 resourceMgr *rsrcMgr.OpenOltResourceMgr
Gamze Abakafee36392019-10-03 11:17:24 +0000174 onuIdsLock sync.RWMutex
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530175 flowsUsedByGemPort map[gemPortKey][]uint32 //gem port id to flow ids
176 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
177 onuGemInfo map[uint32][]rsrcMgr.OnuGemInfo //onu, gem and uni info local cache
178 lockCache sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +0530179}
180
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700181//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530182func NewFlowManager(dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
manikkaraj kbf256be2019-03-25 00:13:48 +0530183 log.Info("Initializing flow manager")
184 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530185 var err error
186 var idx uint32
187
manikkaraj kbf256be2019-03-25 00:13:48 +0530188 flowMgr.deviceHandler = dh
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530189 flowMgr.resourceMgr = rMgr
kdarapub26b4502019-10-05 03:02:33 +0530190 flowMgr.techprofile = make([]tp.TechProfileIf, MaxPonPorts)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530191 if err = flowMgr.populateTechProfilePerPonPort(); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530192 log.Error("Error while populating tech profile mgr\n")
193 return nil
194 }
William Kurkian740a09c2019-10-23 17:07:38 -0400195 flowMgr.onuIdsLock = sync.RWMutex{}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530196 flowMgr.flowsUsedByGemPort = make(map[gemPortKey][]uint32)
197 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
198 flowMgr.onuGemInfo = make(map[uint32][]rsrcMgr.OnuGemInfo)
199 ponPorts := rMgr.DevInfo.GetPonPorts()
200 //Load the onugem info cache from kv store on flowmanager start
201 for idx = 0; idx < ponPorts; idx++ {
202 if flowMgr.onuGemInfo[idx], err = rMgr.GetOnuGemInfo(idx); err != nil {
203 log.Error("Failed to load onu gem info cache")
204 }
205 }
206 flowMgr.lockCache = sync.RWMutex{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530207 log.Info("Initialization of flow manager success!!")
208 return &flowMgr
209}
210
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700211func (f *OpenOltFlowMgr) generateStoredFlowID(flowID uint32, direction string) (uint64, error) {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700212 if direction == Upstream {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400213 log.Debug("upstream flow, shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700214 return 0x1<<15 | uint64(flowID), nil
David K. Bainbridge82efc492019-09-04 09:57:11 -0700215 } else if direction == Downstream {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400216 log.Debug("downstream flow, not shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700217 return uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400218 } else {
219 log.Debug("Unrecognized direction")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700220 return 0, fmt.Errorf("unrecognized direction %s", direction)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400221 }
222}
223
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700224func (f *OpenOltFlowMgr) registerFlow(flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400225 log.Debug("Registering Flow for Device ", log.Fields{"flow": flowFromCore},
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700226 log.Fields{"device": f.deviceHandler.deviceID})
Gamze Abakafee36392019-10-03 11:17:24 +0000227 gemPK := gemPortKey{uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId)}
228 flowIDList, ok := f.flowsUsedByGemPort[gemPK]
229 if !ok {
230 flowIDList = []uint32{deviceFlow.FlowId}
231 }
232 flowIDList = appendUnique(flowIDList, deviceFlow.FlowId)
233 f.flowsUsedByGemPort[gemPK] = flowIDList
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400234}
235
salmansiddiqui7ac62132019-08-22 03:58:50 +0000236func (f *OpenOltFlowMgr) divideAndAddFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32,
237 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
238 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) {
Gamze Abakafee36392019-10-03 11:17:24 +0000239 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530240 var gemPorts []uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400241 var TpInst *tp.TechProfile
manikkaraj kbf256be2019-03-25 00:13:48 +0530242
Manikkaraj kb1d51442019-07-23 10:41:02 -0400243 log.Infow("Dividing flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "portNo": portNo,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000244 "classifier": classifierInfo, "action": actionInfo, "UsMeterID": UsMeterID, "DsMeterID": DsMeterID, "TpID": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400245 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
246 // is because the flow is an NNI flow and there would be no onu resources associated with it
247 // TODO: properly deal with NNI flows
Manikkaraj kb1d51442019-07-23 10:41:02 -0400248 if onuID <= 0 {
Matt Jeanneret77199612019-07-26 18:08:35 -0400249 log.Errorw("No onu id for flow", log.Fields{"portNo": portNo, "classifer": classifierInfo, "action": actionInfo})
manikkaraj kbf256be2019-03-25 00:13:48 +0530250 return
251 }
252
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530253 uni := getUniPortPath(intfID, int32(onuID), int32(uniID))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400254 log.Debugw("Uni port name", log.Fields{"uni": uni})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000255 allocID, gemPorts, TpInst = f.createTcontGemports(intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
Gamze Abakafee36392019-10-03 11:17:24 +0000256 if allocID == 0 || gemPorts == nil || TpInst == nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400257 log.Error("alloc-id-gem-ports-tp-unavailable")
258 return
259 }
260
261 /* Flows can be added specific to gemport if p-bits are received.
262 * If no pbit mentioned then adding flows for all gemports
manikkaraj kbf256be2019-03-25 00:13:48 +0530263 */
Manikkaraj kb1d51442019-07-23 10:41:02 -0400264
265 args := make(map[string]uint32)
Gamze Abakafee36392019-10-03 11:17:24 +0000266 args[IntfID] = intfID
267 args[OnuID] = onuID
268 args[UniID] = uniID
269 args[PortNo] = portNo
270 args[AllocID] = allocID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400271
Gamze Abakafee36392019-10-03 11:17:24 +0000272 f.checkAndAddFlow(args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530273}
274
salmansiddiqui7ac62132019-08-22 03:58:50 +0000275// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
Gamze Abakafee36392019-10-03 11:17:24 +0000276func (f *OpenOltFlowMgr) CreateSchedulerQueues(sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400277
Gamze Abakafee36392019-10-03 11:17:24 +0000278 log.Debugw("CreateSchedulerQueues", log.Fields{"Dir": sq.direction, "IntfID": sq.intfID,
279 "OnuID": sq.onuID, "UniID": sq.uniID, "TpID": sq.tpID, "MeterID": sq.meterID,
280 "TpInst": sq.tpInst, "flowMetadata": sq.flowMetadata})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400281
Gamze Abakafee36392019-10-03 11:17:24 +0000282 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000283 if err != nil {
284 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400285 }
286
287 /* Lets make a simple assumption that if the meter-id is present on the KV store,
288 * then the scheduler and queues configuration is applied on the OLT device
289 * in the given direction.
290 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000291
Manikkaraj kb1d51442019-07-23 10:41:02 -0400292 var SchedCfg *tp_pb.SchedulerConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000293 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400294 if err != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000295 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 -0400296 return err
297 }
298 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000299 if KvStoreMeter.MeterId == sq.meterID {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400300 log.Debug("Scheduler already created for upstream")
301 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400302 }
Gamze Abakafee36392019-10-03 11:17:24 +0000303 log.Errorw("Dynamic meter update not supported", log.Fields{"KvStoreMeterId": KvStoreMeter.MeterId, "MeterID-in-flow": sq.meterID})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000304 return errors.New("invalid-meter-id-in-flow")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400305 }
Gamze Abakafee36392019-10-03 11:17:24 +0000306 log.Debugw("Meter-does-not-exist-Creating-new", log.Fields{"MeterID": sq.meterID, "Direction": Direction})
307 if sq.direction == tp_pb.Direction_UPSTREAM {
308 SchedCfg = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
309 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
310 SchedCfg = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400311 }
312 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000313 if sq.flowMetadata != nil {
314 for _, meter := range sq.flowMetadata.Meters {
315 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400316 meterConfig = meter
317 log.Debugw("Found-meter-config-from-flowmetadata", log.Fields{"meterConfig": meterConfig})
318 break
319 }
320 }
321 } else {
322 log.Error("Flow-metadata-is-not-present-in-flow")
323 }
324 if meterConfig == nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000325 log.Errorw("Could-not-get-meterbands-from-flowMetadata", log.Fields{"flowMetadata": sq.flowMetadata,
326 "MeterID": sq.meterID})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000327 return errors.New("failed-to-get-meter-from-flowMetadata")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400328 } else if len(meterConfig.Bands) < MaxMeterBand {
Gamze Abakafee36392019-10-03 11:17:24 +0000329 log.Errorw("Invalid-number-of-bands-in-meter", log.Fields{"Bands": meterConfig.Bands, "MeterID": sq.meterID})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000330 return errors.New("invalid-number-of-bands-in-meter")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400331 }
332 cir := meterConfig.Bands[0].Rate
333 cbs := meterConfig.Bands[0].BurstSize
334 eir := meterConfig.Bands[1].Rate
335 ebs := meterConfig.Bands[1].BurstSize
336 pir := cir + eir
337 pbs := cbs + ebs
338 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
339
Gamze Abakafee36392019-10-03 11:17:24 +0000340 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Manikkaraj kb1d51442019-07-23 10:41:02 -0400341
342 log.Debugw("Sending Traffic scheduler create to device", log.Fields{"Direction": Direction, "TrafficScheds": TrafficSched})
343 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000344 IntfId: sq.intfID, OnuId: sq.onuID,
345 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400346 TrafficScheds: TrafficSched}); err != nil {
347 log.Errorw("Failed to create traffic schedulers", log.Fields{"error": err})
348 return err
349 }
350 // On receiving the CreateTrafficQueues request, the driver should create corresponding
351 // downstream queues.
Gamze Abakafee36392019-10-03 11:17:24 +0000352 trafficQueues := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400353 log.Debugw("Sending Traffic Queues create to device", log.Fields{"Direction": Direction, "TrafficQueues": trafficQueues})
354 if _, err := f.deviceHandler.Client.CreateTrafficQueues(context.Background(),
Gamze Abakafee36392019-10-03 11:17:24 +0000355 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
356 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400357 TrafficQueues: trafficQueues}); err != nil {
358 log.Errorw("Failed to create traffic queues in device", log.Fields{"error": err})
359 return err
360 }
361
salmansiddiqui7ac62132019-08-22 03:58:50 +0000362 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400363 * store the meter id on the KV store, for further reference.
364 */
Gamze Abakafee36392019-10-03 11:17:24 +0000365 if err := f.resourceMgr.UpdateMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterConfig); err != nil {
366 log.Error("Failed to update meter id for onu %d, meterid %d", sq.onuID, sq.meterID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400367 return err
368 }
369 log.Debugw("updated-meter-info into KV store successfully", log.Fields{"Direction": Direction,
370 "Meter": meterConfig})
371 return nil
372}
373
salmansiddiqui7ac62132019-08-22 03:58:50 +0000374// 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 +0000375func (f *OpenOltFlowMgr) RemoveSchedulerQueues(sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400376
377 var Direction string
378 var SchedCfg *tp_pb.SchedulerConfig
379 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000380 log.Debugw("Removing schedulers and Queues in OLT", log.Fields{"Direction": sq.direction, "IntfID": sq.intfID,
381 "OnuID": sq.onuID, "UniID": sq.uniID, "UniPort": sq.uniPort})
382 if sq.direction == tp_pb.Direction_UPSTREAM {
383 SchedCfg = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400384 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000385 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
386 SchedCfg = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400387 Direction = "downstream"
388 }
389
Gamze Abakafee36392019-10-03 11:17:24 +0000390 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400391 if err != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000392 log.Errorf("Failed to get Meter for Onu %d", sq.onuID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400393 return err
394 }
395 if KVStoreMeter == nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000396 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 -0400397 return nil
398 }
399 cir := KVStoreMeter.Bands[0].Rate
400 cbs := KVStoreMeter.Bands[0].BurstSize
401 eir := KVStoreMeter.Bands[1].Rate
402 ebs := KVStoreMeter.Bands[1].BurstSize
403 pir := cir + eir
404 pbs := cbs + ebs
405
406 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
407
Gamze Abakafee36392019-10-03 11:17:24 +0000408 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
409 TrafficQueues := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400410
411 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(context.Background(),
Gamze Abakafee36392019-10-03 11:17:24 +0000412 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
413 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400414 TrafficQueues: TrafficQueues}); err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000415 log.Errorw("Failed to remove traffic queues", log.Fields{"error": err})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400416 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400417 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000418 log.Debug("Removed traffic queues successfully")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400419 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000420 IntfId: sq.intfID, OnuId: sq.onuID,
421 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400422 TrafficScheds: TrafficSched}); err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000423 log.Errorw("failed to remove traffic schedulers", log.Fields{"error": err})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400424 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400425 }
426
salmansiddiqui7ac62132019-08-22 03:58:50 +0000427 log.Debug("Removed traffic schedulers successfully")
428
429 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400430 * delete the meter id on the KV store.
431 */
Gamze Abakafee36392019-10-03 11:17:24 +0000432 err = f.resourceMgr.RemoveMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400433 if err != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000434 log.Errorf("Failed to remove meter for onu %d, meter id %d", sq.onuID, KVStoreMeter.MeterId)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000435 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400436 }
437 log.Debugw("Removed-meter-from-KV-store successfully", log.Fields{"MeterId": KVStoreMeter.MeterId, "dir": Direction})
438 return err
439}
440
Gamze Abakafee36392019-10-03 11:17:24 +0000441// This function allocates tconts and GEM ports for an ONU
442func (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) {
443 var allocIDs []uint32
444 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530445 var gemPortIDs []uint32
Gamze Abakafee36392019-10-03 11:17:24 +0000446
447 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(intfID, onuID, uniID)
448 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400449
450 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530451
452 log.Infow("creating-new-tcont-and-gem", log.Fields{"pon": intfID, "onu": onuID, "uni": uniID})
453
Manikkaraj kb1d51442019-07-23 10:41:02 -0400454 // Check tech profile instance already exists for derived port name
Girish Gowdra54934262019-11-13 14:19:55 +0530455 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000456 if techProfileInstance == nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530457 log.Infow("tp-instance-not-found--creating-new", log.Fields{"path": tpPath})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000458 techProfileInstance = f.techprofile[intfID].CreateTechProfInstance(TpID, uni, intfID)
459 if techProfileInstance == nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530460 // This should not happen, something wrong in KV backend transaction
461 log.Error("tp-instance-create-failed")
Gamze Abakafee36392019-10-03 11:17:24 +0000462 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530463 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000464 f.resourceMgr.UpdateTechProfileIDForOnu(intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530465 } else {
466 log.Debugw("Tech-profile-instance-already-exist-for-given port-name", log.Fields{"uni": uni})
467 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400468 if UsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000469 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
470 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
471 if err := f.CreateSchedulerQueues(sq); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400472 log.Errorw("CreateSchedulerQueues Failed-upstream", log.Fields{"error": err, "meterID": UsMeterID})
Gamze Abakafee36392019-10-03 11:17:24 +0000473 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400474 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530475 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400476 if DsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000477 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
478 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
479 if err := f.CreateSchedulerQueues(sq); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400480 log.Errorw("CreateSchedulerQueues Failed-downstream", log.Fields{"error": err, "meterID": DsMeterID})
Gamze Abakafee36392019-10-03 11:17:24 +0000481 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400482 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530483 }
Gamze Abakafee36392019-10-03 11:17:24 +0000484
485 allocID := techProfileInstance.UsScheduler.AllocID
486 allocIDs = appendUnique(allocIDs, allocID)
487
488 for _, gem := range techProfileInstance.UpstreamGemPortAttributeList {
489 allgemPortIDs = appendUnique(allgemPortIDs, gem.GemportID)
490 gemPortIDs = append(gemPortIDs, gem.GemportID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400491 }
Gamze Abakafee36392019-10-03 11:17:24 +0000492
493 log.Debugw("Allocated Tcont and GEM ports", log.Fields{"allocIDs": allocIDs, "gemports": allgemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530494 // Send Tconts and GEM ports to KV store
Gamze Abakafee36392019-10-03 11:17:24 +0000495 f.storeTcontsGEMPortsIntoKVStore(intfID, onuID, uniID, allocIDs, allgemPortIDs)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000496 return allocID, gemPortIDs, techProfileInstance
manikkaraj kbf256be2019-03-25 00:13:48 +0530497}
498
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700499func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530500
501 log.Debugw("Storing allocated Tconts and GEM ports into KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700502 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "allocID": allocID, "gemPortIDs": gemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530503 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700504 if err := f.resourceMgr.UpdateAllocIdsForOnu(intfID, onuID, uniID, allocID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530505 log.Error("Errow while uploading allocID to KV store")
506 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700507 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(intfID, onuID, uniID, gemPortIDs); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530508 log.Error("Errow while uploading GEMports to KV store")
509 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700510 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(gemPortIDs, intfID, onuID, uniID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530511 log.Error("Errow while uploading gemtopon map to KV store")
512 }
513 log.Debug("Stored tconts and GEM into KV store successfully")
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400514 for _, gemPort := range gemPortIDs {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700515 f.addGemPortToOnuInfoMap(intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400516 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530517}
518
519func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000520 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530521 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000522 for _, intfID := range techRange.IntfIds {
523 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400524 tpCount++
salmansiddiqui7ac62132019-08-22 03:58:50 +0000525 log.Debugw("Init tech profile done", log.Fields{"intfID": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530526 }
527 }
528 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400529 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530530 log.Errorw("Error while populating techprofile",
Manikkaraj kb1d51442019-07-23 10:41:02 -0400531 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000532 return errors.New("error while populating techprofile mgrs")
manikkaraj kbf256be2019-03-25 00:13:48 +0530533 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400534 log.Infow("Populated techprofile for ponports successfully",
535 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
manikkaraj kbf256be2019-03-25 00:13:48 +0530536 return nil
537}
538
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700539func (f *OpenOltFlowMgr) addUpstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530540 portNo uint32, uplinkClassifier map[string]interface{},
541 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700542 allocID uint32, gemportID uint32) {
543 uplinkClassifier[PacketTagType] = SingleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530544 log.Debugw("Adding upstream data flow", log.Fields{"uplinkClassifier": uplinkClassifier, "uplinkAction": uplinkAction})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700545 f.addHSIAFlow(intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700546 Upstream, logicalFlow, allocID, gemportID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530547 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530548}
549
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700550func (f *OpenOltFlowMgr) addDownstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530551 portNo uint32, downlinkClassifier map[string]interface{},
552 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700553 allocID uint32, gemportID uint32) {
554 downlinkClassifier[PacketTagType] = DoubleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530555 log.Debugw("Adding downstream data flow", log.Fields{"downlinkClassifier": downlinkClassifier,
556 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400557 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
558 if vlan, exists := downlinkClassifier[VlanVid]; exists {
559 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700560 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Manikkaraj kb1d51442019-07-23 10:41:02 -0400561 if uint32(metadata.(uint64)) == MkUniPortNum(intfID, onuID, uniID) {
562 log.Infow("Ignoring DL trap device flow from core", log.Fields{"flow": logicalFlow})
563 return
564 }
565 }
566 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530567 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400568
Manikkaraj k884c1242019-04-11 16:26:42 +0530569 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700570 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400571 // vlan_vid is a uint32. must be type asserted as such or conversion fails
572 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530573 if ok {
574 downlinkAction[VlanVid] = dlClVid & 0xfff
575 } else {
576 log.Error("dl-classifier-vid-type-conversion-failed")
577 return
578 }
579
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700580 f.addHSIAFlow(intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700581 Downstream, logicalFlow, allocID, gemportID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530582}
583
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700584func (f *OpenOltFlowMgr) addHSIAFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +0530585 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700586 allocID uint32, gemPortID uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530587 var networkIntfID uint32
Manikkaraj k884c1242019-04-11 16:26:42 +0530588 /* One of the OLT platform (Broadcom BAL) requires that symmetric
589 flows require the same flow_id to be used across UL and DL.
590 Since HSIA flow is the only symmetric flow currently, we need to
591 re-use the flow_id across both direction. The 'flow_category'
592 takes priority over flow_cookie to find any available HSIA_FLOW
593 id for the ONU.
594 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700595 log.Debugw("Adding HSIA flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "classifier": classifier,
596 "action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530597 "logicalFlow": *logicalFlow})
Gamze Abakafee36392019-10-03 11:17:24 +0000598 var vlanPbit uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400599 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000600 vlanPbit = classifier[VlanPcp].(uint32)
601 log.Debugw("Found pbit in the flow", log.Fields{"VlanPbit": vlanPbit})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400602 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700603 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530604 flowID, err := f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530605 if err != nil {
606 log.Errorw("Flow id unavailable for HSIA flow", log.Fields{"direction": direction})
607 return
608 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700609 var classifierProto *openoltpb2.Classifier
610 var actionProto *openoltpb2.Action
Manikkaraj k884c1242019-04-11 16:26:42 +0530611 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
612 log.Error("Error in making classifier protobuf for hsia flow")
613 return
614 }
615 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
616 if actionProto = makeOpenOltActionField(action); actionProto == nil {
617 log.Errorw("Error in making action protobuf for hsia flow", log.Fields{"direction": direction})
618 return
619 }
620 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530621 networkIntfID, err = getNniIntfID(classifier, action)
622 if err != nil {
623 log.Error("Failed to get nniIntf ID")
624 return
625 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700626 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
627 OnuId: int32(onuID),
628 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000629 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530630 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700631 AllocId: int32(allocID),
632 NetworkIntfId: int32(networkIntfID),
633 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530634 Classifier: classifierProto,
635 Action: actionProto,
636 Priority: int32(logicalFlow.Priority),
637 Cookie: logicalFlow.Cookie,
638 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400639 if ok := f.addFlowToDevice(logicalFlow, &flow); ok {
Manikkaraj k884c1242019-04-11 16:26:42 +0530640 log.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530641 flowsToKVStore := f.getUpdatedFlowInfo(&flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
Manikkaraj k884c1242019-04-11 16:26:42 +0530642 if err := f.updateFlowInfoToKVStore(flow.AccessIntfId,
643 flow.OnuId,
644 flow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400645 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530646 log.Errorw("Error uploading HSIA flow into KV store", log.Fields{"flow": flow, "direction": direction, "error": err})
647 return
648 }
649 }
650}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700651func (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 +0530652
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700653 var dhcpFlow openoltpb2.Flow
654 var actionProto *openoltpb2.Action
655 var classifierProto *openoltpb2.Classifier
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530656 var flowID uint32
657 networkIntfID, err := getNniIntfID(classifier, action)
658 if err != nil {
659 log.Error("Failed to get nniIntf ID")
660 return
661 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530662
663 // Clear the action map
664 for k := range action {
665 delete(action, k)
666 }
667
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700668 action[TrapToHost] = true
669 classifier[UDPSrc] = uint32(68)
670 classifier[UDPDst] = uint32(67)
671 classifier[PacketTagType] = SingleTag
672 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530673
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700674 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530675
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530676 flowID, err = f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0 /*classifier[VLAN_PCP].(uint32)*/)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530677
678 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700679 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530680 return
681 }
682
683 log.Debugw("Creating UL DHCP flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID})
684
685 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
686 log.Error("Error in making classifier protobuf for ul flow")
687 return
688 }
689 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
690 if actionProto = makeOpenOltActionField(action); actionProto == nil {
691 log.Error("Error in making action protobuf for ul flow")
692 return
693 }
694
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700695 dhcpFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
696 OnuId: int32(onuID),
697 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530698 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700699 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700700 AllocId: int32(allocID),
701 NetworkIntfId: int32(networkIntfID),
702 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530703 Classifier: classifierProto,
704 Action: actionProto,
705 Priority: int32(logicalFlow.Priority),
706 Cookie: logicalFlow.Cookie,
707 PortNo: portNo}
708
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400709 if ok := f.addFlowToDevice(logicalFlow, &dhcpFlow); ok {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530710 log.Debug("DHCP UL flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530711 flowsToKVStore := f.getUpdatedFlowInfo(&dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530712 if err := f.updateFlowInfoToKVStore(dhcpFlow.AccessIntfId,
713 dhcpFlow.OnuId,
714 dhcpFlow.UniId,
715 dhcpFlow.FlowId, flowsToKVStore); err != nil {
716 log.Errorw("Error uploading DHCP UL flow into KV store", log.Fields{"flow": dhcpFlow, "error": err})
717 return
718 }
719 }
720
manikkaraj kbf256be2019-03-25 00:13:48 +0530721 return
722}
723
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700724// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530725func (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 -0700726 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 +0530727
728 uplinkClassifier := make(map[string]interface{})
729 uplinkAction := make(map[string]interface{})
730 downlinkClassifier := make(map[string]interface{})
731 downlinkAction := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700732 var upstreamFlow openoltpb2.Flow
733 var downstreamFlow openoltpb2.Flow
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530734 var networkIntfID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530735
736 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700737 uplinkClassifier[EthType] = uint32(EapEthType)
738 uplinkClassifier[PacketTagType] = SingleTag
739 uplinkClassifier[VlanVid] = vlanID
manikkaraj kbf256be2019-03-25 00:13:48 +0530740 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700741 uplinkAction[TrapToHost] = true
742 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530743 //Add Uplink EAPOL Flow
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530744 uplinkFlowID, err := f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530745 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700746 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manikkaraj k884c1242019-04-11 16:26:42 +0530747 return
manikkaraj kbf256be2019-03-25 00:13:48 +0530748 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700749 var classifierProto *openoltpb2.Classifier
750 var actionProto *openoltpb2.Action
751 log.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530752
753 if classifierProto = makeOpenOltClassifierField(uplinkClassifier); classifierProto == nil {
754 log.Error("Error in making classifier protobuf for ul flow")
755 return
756 }
757 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
758 if actionProto = makeOpenOltActionField(uplinkAction); actionProto == nil {
759 log.Error("Error in making action protobuf for ul flow")
760 return
761 }
762 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530763 networkIntfID, err = getNniIntfID(classifier, action)
764 if err != nil {
765 log.Error("Failed to get nniIntf ID")
766 return
767 }
768
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700769 upstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
770 OnuId: int32(onuID),
771 UniId: int32(uniID),
772 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700773 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700774 AllocId: int32(allocID),
775 NetworkIntfId: int32(networkIntfID),
776 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530777 Classifier: classifierProto,
778 Action: actionProto,
779 Priority: int32(logicalFlow.Priority),
780 Cookie: logicalFlow.Cookie,
781 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400782 if ok := f.addFlowToDevice(logicalFlow, &upstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530783 log.Debug("EAPOL UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400784 flowCategory := "EAPOL"
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530785 flowsToKVStore := f.getUpdatedFlowInfo(&upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
manikkaraj kbf256be2019-03-25 00:13:48 +0530786 if err := f.updateFlowInfoToKVStore(upstreamFlow.AccessIntfId,
787 upstreamFlow.OnuId,
788 upstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400789 upstreamFlow.FlowId,
790 /* lowCategory, */
791 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530792 log.Errorw("Error uploading EAPOL UL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
793 return
794 }
795 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400796 // Dummy Downstream flow due to BAL 2.6 limitation
797 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530798 /* Add Downstream EAPOL Flow, Only for first EAP flow (BAL
799 # requirement)
800 # On one of the platforms (Broadcom BAL), when same DL classifier
801 # vlan was used across multiple ONUs, eapol flow re-adds after
802 # flow delete (cases of onu reboot/disable) fails.
803 # In order to generate unique vlan, a combination of intf_id
804 # onu_id and uniId is used.
805 # uniId defaults to 0, so add 1 to it.
806 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700807 log.Debugw("Creating DL EAPOL flow with default vlan", log.Fields{"vlan": vlanID})
808 specialVlanDlFlow := 4090 - intfID*onuID*(uniID+1)
manikkaraj kbf256be2019-03-25 00:13:48 +0530809 // Assert that we do not generate invalid vlans under no condition
810 if specialVlanDlFlow <= 2 {
811 log.Fatalw("invalid-vlan-generated", log.Fields{"vlan": specialVlanDlFlow})
812 return
813 }
814 log.Debugw("specialVlanEAPOLDlFlow:", log.Fields{"dl_vlan": specialVlanDlFlow})
815 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700816 downlinkClassifier[PacketTagType] = SingleTag
Manikkaraj kb1d51442019-07-23 10:41:02 -0400817 downlinkClassifier[EthType] = uint32(EapEthType)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700818 downlinkClassifier[VlanVid] = uint32(specialVlanDlFlow)
manikkaraj kbf256be2019-03-25 00:13:48 +0530819 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700820 downlinkAction[PushVlan] = true
821 downlinkAction[VlanVid] = vlanID
822 flowStoreCookie := getFlowStoreCookie(downlinkClassifier, gemPortID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530823 downlinkFlowID, err := f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530824 if err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530825 log.Errorw("flowId unavailable for DL EAPOL",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700826 log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
manikkaraj kbf256be2019-03-25 00:13:48 +0530827 return
828 }
829 log.Debugw("Creating DL EAPOL flow",
salmansiddiqui7ac62132019-08-22 03:58:50 +0000830 log.Fields{"dl_classifier": downlinkClassifier, "dl_action": downlinkAction, "downlinkFlowID": downlinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530831 if classifierProto = makeOpenOltClassifierField(downlinkClassifier); classifierProto == nil {
832 log.Error("Error in making classifier protobuf for downlink flow")
833 return
834 }
835 if actionProto = makeOpenOltActionField(downlinkAction); actionProto == nil {
836 log.Error("Error in making action protobuf for dl flow")
837 return
838 }
839 // Downstream flow in grpc protobuf
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700840 downstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
841 OnuId: int32(onuID),
842 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000843 FlowId: downlinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700844 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700845 AllocId: int32(allocID),
846 NetworkIntfId: int32(networkIntfID),
847 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530848 Classifier: classifierProto,
849 Action: actionProto,
850 Priority: int32(logicalFlow.Priority),
851 Cookie: logicalFlow.Cookie,
852 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400853 if ok := f.addFlowToDevice(logicalFlow, &downstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530854 log.Debug("EAPOL DL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400855 flowCategory := ""
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530856 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamFlow, flowStoreCookie, flowCategory, downlinkFlowID, logicalFlow.Id)
manikkaraj kbf256be2019-03-25 00:13:48 +0530857 if err := f.updateFlowInfoToKVStore(downstreamFlow.AccessIntfId,
858 downstreamFlow.OnuId,
859 downstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400860 downstreamFlow.FlowId,
861 /* flowCategory, */
862 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530863 log.Errorw("Error uploading EAPOL DL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
864 return
865 }
866 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530867 }
868 log.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
869}
870
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700871func makeOpenOltClassifierField(classifierInfo map[string]interface{}) *openoltpb2.Classifier {
872 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -0700873
874 classifier.EthType, _ = classifierInfo[EthType].(uint32)
875 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
876 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
877 vid := vlanID & VlanvIDMask
878 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -0400879 classifier.OVid = vid
880 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530881 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700882 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
883 vid := uint32(metadata)
884 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -0400885 classifier.IVid = vid
886 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530887 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700888 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400889 if vlanPcp == 0 {
890 classifier.OPbits = VlanPCPMask
891 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700892 classifier.OPbits = vlanPcp & VlanPCPMask
Manikkaraj kb1d51442019-07-23 10:41:02 -0400893 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530894 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700895 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
896 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
897 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
898 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
899 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
900 classifier.PktTagType = pktTagType
901
902 switch pktTagType {
903 case SingleTag:
904 case DoubleTag:
905 case Untagged:
906 default:
manikkaraj kbf256be2019-03-25 00:13:48 +0530907 log.Error("Invalid tag type in classifier") // should not hit
908 return nil
909 }
910 }
911 return &classifier
912}
913
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700914func makeOpenOltActionField(actionInfo map[string]interface{}) *openoltpb2.Action {
915 var actionCmd openoltpb2.ActionCmd
916 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +0530917 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700918 if _, ok := actionInfo[PopVlan]; ok {
919 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530920 action.Cmd.RemoveOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700921 } else if _, ok := actionInfo[PushVlan]; ok {
922 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530923 action.Cmd.AddOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700924 } else if _, ok := actionInfo[TrapToHost]; ok {
925 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +0530926 } else {
927 log.Errorw("Invalid-action-field", log.Fields{"action": actionInfo})
928 return nil
929 }
930 return &action
931}
932
Manikkaraj kb1d51442019-07-23 10:41:02 -0400933func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uni string, TpID uint32) string {
934 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530935}
936
Gamze Abakafee36392019-10-03 11:17:24 +0000937// DeleteTechProfileInstances removes the tech profile instances from persistent storage
938func (f *OpenOltFlowMgr) DeleteTechProfileInstances(intfID uint32, onuID uint32, uniID uint32, sn string) error {
939 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(intfID, onuID, uniID)
Devmalya Paul495b94a2019-08-27 19:42:00 -0400940 uniPortName := fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +0000941 for _, tpID := range tpIDList {
942 if err := f.DeleteTechProfileInstance(intfID, onuID, uniID, uniPortName, tpID); err != nil {
943 log.Debugw("Failed-to-delete-tp-instance-from-kv-store", log.Fields{"tp-id": tpID, "uni-port-name": uniPortName})
Girish Gowdra54934262019-11-13 14:19:55 +0530944 // return err
945 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +0000946 }
947 }
948 return nil
949}
950
951// DeleteTechProfileInstance removes the tech profile instance from persistent storage
952func (f *OpenOltFlowMgr) DeleteTechProfileInstance(intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
953 if uniPortName == "" {
954 uniPortName = fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
955 }
Devmalya Paul495b94a2019-08-27 19:42:00 -0400956 if err := f.techprofile[intfID].DeleteTechProfileInstance(tpID, uniPortName); err != nil {
957 log.Debugw("Failed-to-delete-tp-instance-from-kv-store", log.Fields{"tp-id": tpID, "uni-port-name": uniPortName})
958 return err
959 }
960 return nil
961}
962
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700963func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530964 if len(classifier) == 0 { // should never happen
965 log.Error("Invalid classfier object")
966 return 0
967 }
968 var jsonData []byte
969 var flowString string
970 var err error
971 // TODO: Do we need to marshall ??
972 if jsonData, err = json.Marshal(classifier); err != nil {
973 log.Error("Failed to encode classifier")
974 return 0
975 }
976 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700977 if gemPortID != 0 {
978 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +0530979 }
980 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700981 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +0530982 hash := big.NewInt(0)
983 hash.SetBytes(h.Sum(nil))
984 return hash.Uint64()
985}
986
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530987func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openoltpb2.Flow, flowStoreCookie uint64, flowCategory string, deviceFlowID uint32, logicalFlowID uint64) *[]rsrcMgr.FlowInfo {
988 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700989 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400990 /* For flows which trap out of the NNI, the AccessIntfId is invalid
991 (set to -1). In such cases, we need to refer to the NetworkIntfId .
992 */
993 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700994 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400995 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700996 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400997 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700998 // Get existing flows matching flowid for given subscriber from KV store
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530999 existingFlows := f.resourceMgr.GetFlowIDInfo(intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001000 if existingFlows != nil {
1001 log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001002 //for _, f := range *existingFlows {
1003 // flows = append(flows, f)
1004 //}
1005 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001006 }
1007 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 +05301008 return &flows
1009}
1010
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001011//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
1012// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
1013// var intfId uint32
1014// /* For flows which trap out of the NNI, the AccessIntfId is invalid
1015// (set to -1). In such cases, we need to refer to the NetworkIntfId .
1016// */
1017// if flow.AccessIntfId != -1 {
1018// intfId = uint32(flow.AccessIntfId)
1019// } else {
1020// intfId = uint32(flow.NetworkIntfId)
1021// }
1022// // Get existing flows matching flowid for given subscriber from KV store
1023// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
1024// if existingFlows != nil {
1025// log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
1026// for _, f := range *existingFlows {
1027// flows = append(flows, f)
1028// }
1029// }
1030// log.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
1031// return &flows
1032//}
1033
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001034func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
manikkaraj k17652a72019-05-06 09:06:36 -04001035 log.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001036 if err := f.resourceMgr.UpdateFlowIDInfo(intfID, onuID, uniID, flowID, flows); err != nil {
manikkaraj k17652a72019-05-06 09:06:36 -04001037 log.Debug("Error while Storing flow into KV store")
1038 return err
1039 }
1040 log.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +05301041 return nil
1042}
1043
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001044func (f *OpenOltFlowMgr) addFlowToDevice(logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) bool {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001045
1046 var intfID uint32
1047 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1048 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1049 */
1050 if deviceFlow.AccessIntfId != -1 {
1051 intfID = uint32(deviceFlow.AccessIntfId)
1052 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001053 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001054 intfID = uint32(deviceFlow.NetworkIntfId)
1055 }
1056
manikkaraj kbf256be2019-03-25 00:13:48 +05301057 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1058 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001059
1060 st, _ := status.FromError(err)
1061 if st.Code() == codes.AlreadyExists {
Gamze Abakafee36392019-10-03 11:17:24 +00001062 log.Debug("Flow already exists", log.Fields{"err": err, "deviceFlow": deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301063 return false
1064 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001065
1066 if err != nil {
1067 log.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": deviceFlow})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001068 f.resourceMgr.FreeFlowID(intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001069 return false
1070 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001071 f.registerFlow(logicalFlow, deviceFlow)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301072 log.Debugw("Flow added to device successfully ", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001073 return true
1074}
1075
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001076func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) bool {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001077 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1078 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1079 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001080 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
1081 log.Warnw("Can not remove flow from device since it's unreachable", log.Fields{"err": err, "deviceFlow": deviceFlow})
1082 //Assume the flow is removed
1083 return true
1084 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001085 log.Errorw("Failed to Remove flow from device", log.Fields{"err": err, "deviceFlow": deviceFlow})
1086 return false
serkant.uluderya245caba2019-09-24 23:15:29 -07001087
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001088 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001089 log.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301090 return true
1091}
1092
1093/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1094 //update core flows_proxy : flows_proxy.update('/', flows)
1095}
1096
1097func generateStoredId(flowId uint32, direction string)uint32{
1098
David K. Bainbridge82efc492019-09-04 09:57:11 -07001099 if direction == Upstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301100 log.Debug("Upstream flow shifting flowid")
1101 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001102 }else if direction == Downstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301103 log.Debug("Downstream flow not shifting flowid")
1104 return flowId
1105 }else{
1106 log.Errorw("Unrecognized direction",log.Fields{"direction": direction})
1107 return flowId
1108 }
1109}
1110
1111*/
1112
Humera Kouser94d7a842019-08-25 19:04:32 -04001113func (f *OpenOltFlowMgr) addLLDPFlow(flow *ofp.OfpFlowStats, portNo uint32) {
1114
1115 classifierInfo := make(map[string]interface{})
1116 actionInfo := make(map[string]interface{})
1117
1118 classifierInfo[EthType] = uint32(LldpEthType)
1119 classifierInfo[PacketTagType] = Untagged
1120 actionInfo[TrapToHost] = true
1121
1122 // LLDP flow is installed to trap LLDP packets on the NNI port.
1123 // We manage flow_id resource pool on per PON port basis.
1124 // Since this situation is tricky, as a hack, we pass the NNI port
1125 // index (network_intf_id) as PON port Index for the flow_id resource
1126 // pool. Also, there is no ONU Id available for trapping LLDP packets
1127 // on NNI port, use onu_id as -1 (invalid)
1128 // ****************** CAVEAT *******************
1129 // This logic works if the NNI Port Id falls within the same valid
1130 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1131 // we need to have a re-look at this.
1132 // *********************************************
1133
1134 var onuID = -1
1135 var uniID = -1
1136 var gemPortID = -1
1137
1138 var networkInterfaceID = IntfIDFromNniPortNum(portNo)
1139 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301140 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Humera Kouser94d7a842019-08-25 19:04:32 -04001141 log.Debug("Flow-exists--not-re-adding")
1142 return
1143 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301144 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001145
1146 if err != nil {
1147 log.Errorw("Flow id unavailable for LLDP traponNNI flow", log.Fields{"error": err})
1148 return
1149 }
1150 var classifierProto *openoltpb2.Classifier
1151 var actionProto *openoltpb2.Action
1152 if classifierProto = makeOpenOltClassifierField(classifierInfo); classifierProto == nil {
1153 log.Error("Error in making classifier protobuf for LLDP trap on nni flow")
1154 return
1155 }
1156 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1157 if actionProto = makeOpenOltActionField(actionInfo); actionProto == nil {
1158 log.Error("Error in making action protobuf for LLDP trap on nni flow")
1159 return
1160 }
1161 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
1162
1163 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1164 OnuId: int32(onuID), // OnuId not required
1165 UniId: int32(uniID), // UniId not used
1166 FlowId: flowID,
1167 FlowType: Downstream,
1168 NetworkIntfId: int32(networkInterfaceID),
1169 GemportId: int32(gemPortID),
1170 Classifier: classifierProto,
1171 Action: actionProto,
1172 Priority: int32(flow.Priority),
1173 Cookie: flow.Cookie,
1174 PortNo: portNo}
1175 if ok := f.addFlowToDevice(flow, &downstreamflow); ok {
1176 log.Debug("LLDP trap on NNI flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301177 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID, flow.Id)
Humera Kouser94d7a842019-08-25 19:04:32 -04001178 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1179 int32(onuID),
1180 int32(uniID),
1181 flowID, flowsToKVStore); err != nil {
1182 log.Errorw("Error uploading LLDP flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1183 }
1184 }
1185 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301186}
1187
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301188func getUniPortPath(intfID uint32, onuID int32, uniID int32) string {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001189 return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1190}
1191
1192//getOnuChildDevice to fetch onu
1193func (f *OpenOltFlowMgr) getOnuChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
1194 log.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
1195 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
1196 onuDevice := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301197 if onuDevice == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001198 log.Errorw("onu not found", log.Fields{"intfId": parentPortNo, "onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301199 return nil, errors.New("onu not found")
manikkaraj kbf256be2019-03-25 00:13:48 +05301200 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301201 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1202 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301203}
1204
1205func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001206 log.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301207 return nil
1208}
1209
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001210func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
1211 log.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301212}
1213
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001214func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001215 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001216 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001217 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001218 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001219}
1220
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301221//clearResources clears pon resources in kv store and the device
1222func (f *OpenOltFlowMgr) clearResources(flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
1223 gemPortID int32, flowID uint32, flowDirection string,
1224 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001225
Chaitrashree G S90a17952019-11-14 21:51:21 -05001226 tpID, err := getTpIDFromFlow(flow)
1227 if err != nil {
1228 log.Error("metadata-is-not-present-invalid-flow-to-process", log.Fields{"pon": Intf, "onuID": onuID, "uniID": uniID})
1229 return err
1230 }
Gamze Abakafee36392019-10-03 11:17:24 +00001231
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001232 if len(updatedFlows) >= 0 {
1233 // There are still flows referencing the same flow_id.
1234 // So the flow should not be freed yet.
1235 // For ex: Case of HSIA where same flow is shared
1236 // between DS and US.
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301237 f.updateFlowInfoToKVStore(int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001238 if len(updatedFlows) == 0 {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301239 log.Debugw("Releasing flow Id to resource manager", log.Fields{"Intf": Intf, "onuId": onuID, "uniId": uniID, "flowId": flowID})
1240 f.resourceMgr.FreeFlowID(Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001241
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301242 uni := getUniPortPath(Intf, onuID, uniID)
1243 tpPath := f.getTPpath(Intf, uni, tpID)
Gamze Abakafee36392019-10-03 11:17:24 +00001244 log.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301245 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(tpID, tpPath)
Gamze Abakafee36392019-10-03 11:17:24 +00001246 if err != nil { // This should not happen, something wrong in KV backend transaction
1247 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": 20, "path": tpPath})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301248 return err
Gamze Abakafee36392019-10-03 11:17:24 +00001249 }
1250 if techprofileInst == nil {
1251 log.Errorw("Tech-profile-instance-does-not-exist-in-KV Store", log.Fields{"tpPath": tpPath})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301252 return err
Gamze Abakafee36392019-10-03 11:17:24 +00001253 }
1254
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301255 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00001256 if f.isGemPortUsedByAnotherFlow(gemPK) {
1257 flowIDs := f.flowsUsedByGemPort[gemPK]
1258 for i, flowIDinMap := range flowIDs {
1259 if flowIDinMap == flowID {
1260 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
1261 f.flowsUsedByGemPort[gemPK] = flowIDs
1262 break
1263 }
1264 }
1265 log.Debugw("Gem port id is still used by other flows", log.Fields{"gemPortID": gemPortID, "usedByFlows": flowIDs})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301266 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00001267 }
Gamze Abakafee36392019-10-03 11:17:24 +00001268 log.Debugf("Gem port id %d is not used by another flow - releasing the gem port", gemPortID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301269 f.resourceMgr.RemoveGemPortIDForOnu(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001270 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1271 // 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 +05301272 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(uint32(gemPortID), Intf)
Gamze Abakafee36392019-10-03 11:17:24 +00001273 f.onuIdsLock.Lock()
1274 delete(f.flowsUsedByGemPort, gemPK)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301275 //delete(f.onuGemPortIds, gemPK)
1276 f.resourceMgr.FreeGemPortID(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001277 f.onuIdsLock.Unlock()
1278
Girish Gowdra54934262019-11-13 14:19:55 +05301279 ok, _ := f.isTechProfileUsedByAnotherGem(Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001280 if !ok {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301281 f.resourceMgr.RemoveTechProfileIDForOnu(Intf, uint32(onuID), uint32(uniID), tpID)
1282 f.RemoveSchedulerQueues(schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1283 f.RemoveSchedulerQueues(schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1284 f.DeleteTechProfileInstance(Intf, uint32(onuID), uint32(uniID), "", tpID)
1285 f.resourceMgr.FreeAllocID(Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
Gamze Abakafee36392019-10-03 11:17:24 +00001286 // TODO: Send a "Delete TechProfile" message to ONU to do its own clean up on ONU OMCI stack
1287 }
1288 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001289 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301290 return nil
1291}
1292
1293func (f *OpenOltFlowMgr) clearFlowFromResourceManager(flow *ofp.OfpFlowStats, flowDirection string) {
1294
1295 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowDirection": flowDirection, "flow": *flow})
1296 var updatedFlows []rsrcMgr.FlowInfo
1297 var flowID uint32
1298 var onuID, uniID int32
1299 classifierInfo := make(map[string]interface{})
1300
1301 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
1302 if err != nil {
1303 log.Error(err)
1304 return
1305 }
1306 onuID = int32(onu)
1307 uniID = int32(uni)
1308
1309 for _, field := range flows.GetOfbFields(flow) {
1310 if field.Type == flows.IP_PROTO {
1311 classifierInfo[IPProto] = field.GetIpProto()
1312 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
1313 }
1314 }
1315 log.Debugw("Extracted access info from flow to be deleted",
1316 log.Fields{"ponIntf": Intf, "onuID": onuID, "uniID": uniID})
1317
1318 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1319 onuID = -1
1320 uniID = -1
1321 log.Debug("Trap on nni flow set oni, uni to -1")
1322 Intf = IntfIDFromNniPortNum(inPort)
1323 }
1324 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(Intf, onuID, uniID)
1325 for _, flowID = range flowIds {
1326 flowInfo := f.resourceMgr.GetFlowIDInfo(Intf, onuID, uniID, flowID)
1327 if flowInfo == nil {
1328 log.Debugw("No FlowInfo found found in KV store",
1329 log.Fields{"Intf": Intf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1330 return
1331 }
1332 updatedFlows = nil
1333 for _, flow := range *flowInfo {
1334 updatedFlows = append(updatedFlows, flow)
1335 }
1336
1337 for i, storedFlow := range updatedFlows {
1338 if flow.Id == storedFlow.LogicalFlowID {
1339 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
1340 log.Debugw("Flow to be deleted", log.Fields{"flow": storedFlow})
1341 if ok := f.removeFlowFromDevice(&removeFlowMessage); ok {
1342 log.Debug("Flow removed from device successfully")
1343 //Remove the Flow from FlowInfo
1344 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1345 err = f.clearResources(flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
1346 flowID, flowDirection, portNum, updatedFlows)
1347 if err != nil {
1348 log.Error("Failed to clear resources for flow", log.Fields{"flow": storedFlow})
1349 return
1350 }
1351 } else {
1352 log.Error("Failed to remove flow from device")
1353 return
1354 }
1355 }
1356 }
1357 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001358}
1359
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001360//RemoveFlow removes the flow from the device
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001361func (f *OpenOltFlowMgr) RemoveFlow(flow *ofp.OfpFlowStats) {
1362 log.Debugw("Removing Flow", log.Fields{"flow": flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301363 var direction string
1364 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001365
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301366 for _, action := range flows.GetActions(flow) {
1367 if action.Type == flows.OUTPUT {
1368 if out := action.GetOutput(); out != nil {
1369 actionInfo[Output] = out.GetPort()
1370 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
1371 } else {
1372 log.Error("Invalid output port in action")
1373 return
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001374 }
1375 }
1376 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301377 if IsUpstream(actionInfo[Output].(uint32)) {
1378 direction = Upstream
1379 } else {
1380 direction = Downstream
1381 }
1382
1383 f.clearFlowFromResourceManager(flow, direction) //TODO: Take care of the limitations
1384
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001385 return
1386}
1387
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001388// AddFlow add flow to device
Manikkaraj kb1d51442019-07-23 10:41:02 -04001389func (f *OpenOltFlowMgr) AddFlow(flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001390 classifierInfo := make(map[string]interface{})
1391 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001392 var UsMeterID uint32
1393 var DsMeterID uint32
1394
1395 log.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001396 formulateClassifierInfoFromFlow(classifierInfo, flow)
1397
1398 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
1399 if err != nil {
1400 // Error logging is already done in the called function
1401 // So just return in case of error
1402 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301403 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001404
manikkaraj k17652a72019-05-06 09:06:36 -04001405 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00001406 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
1407 if err != nil {
1408 // error if any, already logged in the called function
1409 return
manikkaraj k17652a72019-05-06 09:06:36 -04001410 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001411
David K. Bainbridge82efc492019-09-04 09:57:11 -07001412 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[Output]})
1413 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00001414
Humera Kouser94d7a842019-08-25 19:04:32 -04001415 if ethType, ok := classifierInfo[EthType]; ok {
1416 if ethType.(uint32) == LldpEthType {
1417 log.Info("Adding LLDP flow")
1418 f.addLLDPFlow(flow, portNo)
1419 return
1420 }
1421 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001422 if ipProto, ok := classifierInfo[IPProto]; ok {
1423 if ipProto.(uint32) == IPProtoDhcp {
1424 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001425 if udpSrc.(uint32) == uint32(67) {
1426 log.Debug("trap-dhcp-from-nni-flow")
1427 f.addDHCPTrapFlowOnNNI(flow, classifierInfo, portNo)
1428 return
1429 }
1430 }
1431 }
1432 }
A R Karthick1f85b802019-10-11 05:06:05 +00001433
1434 f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301435 f.resourceMgr.AddUniPortToOnuInfo(intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00001436
Chaitrashree G S90a17952019-11-14 21:51:21 -05001437 TpID, err := getTpIDFromFlow(flow)
1438 if err != nil {
1439 log.Error("metadata-is-not-present-invalid-flow-to-process", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1440 return
1441 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001442 log.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001443 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07001444 UsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001445 log.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
1446 } else {
Scott Baker355d1742019-10-24 10:57:52 -07001447 DsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001448 log.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
1449
1450 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001451 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001452}
1453
1454//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04001455func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001456
1457 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301458 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001459 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301460 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301461 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301462 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04001463
Manikkaraj kb1d51442019-07-23 10:41:02 -04001464 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001465 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
manikkaraj k17652a72019-05-06 09:06:36 -04001466 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
1467 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1468 tpDownloadMsg,
1469 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
1470 f.deviceHandler.deviceType,
1471 onuDevice.Type,
1472 onuDevice.Id,
1473 onuDevice.ProxyAddress.DeviceId, "")
1474 if sendErr != nil {
1475 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1476 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1477 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1478 return sendErr
1479 }
1480 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05301481 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301482}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001483
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301484//UpdateOnuInfo function adds onu info to cache and kvstore
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001485func (f *OpenOltFlowMgr) UpdateOnuInfo(intfID uint32, onuID uint32, serialNum string) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301486
1487 f.lockCache.Lock()
1488 defer f.lockCache.Unlock()
1489 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
1490 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
1491 if err := f.resourceMgr.AddOnuInfo(intfID, onu); err != nil {
1492 log.Errorw("failed to add onu info", log.Fields{"onu": onu})
1493 return
1494 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001495 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
1496}
1497
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301498//addGemPortToOnuInfoMap function adds GEMport to ONU map
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001499func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(intfID uint32, onuID uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301500 f.lockCache.Lock()
1501 defer f.lockCache.Unlock()
1502 onugem := f.onuGemInfo[intfID]
1503 // update the gem to the local cache as well as to kv strore
1504 for idx, onu := range onugem {
1505 if onu.OnuID == onuID {
1506 // check if gem already exists , else update the cache and kvstore
1507 for _, gem := range onu.GemPorts {
1508 if gem == gemPort {
1509 log.Debugw("Gem already in cache, no need to update cache and kv store",
1510 log.Fields{"gem": gemPort})
1511 return
1512 }
1513 }
1514 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
1515 f.onuGemInfo[intfID] = onugem
1516 }
1517 }
1518 err := f.resourceMgr.AddGemToOnuGemInfo(intfID, onuID, gemPort)
1519 if err != nil {
1520 log.Errorw("Failed to add gem to onu", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001521 return
1522 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001523}
1524
1525// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001526
1527//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
1528func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301529
1530 f.lockCache.Lock()
1531 defer f.lockCache.Unlock()
1532
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001533 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 +05301534 // get onuid from the onugem info cache
1535 onugem := f.onuGemInfo[intfID]
1536 for _, onu := range onugem {
1537 for _, gem := range onu.GemPorts {
1538 if gem == gemPortID {
1539 return onu.OnuID, nil
1540 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001541 }
1542 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001543 log.Errorw("onuid is not found", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPort": gemPortID})
1544 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 -04001545}
1546
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001547//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
1548func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001549 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001550 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001551 var err error
1552
1553 if packetIn.IntfType == "pon" {
1554 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001555 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001556 log.Errorw("Unable to get ONU ID from GEM/PON port", log.Fields{"pon port": packetIn.IntfId, "gemport": packetIn.GemportId})
1557 return logicalPortNum, err
1558 }
1559 if packetIn.PortNo != 0 {
1560 logicalPortNum = packetIn.PortNo
1561 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001562 uniID := uint32(0) // FIXME - multi-uni support
1563 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001564 }
1565 // 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 +05301566 f.UpdateGemPortForPktIn(packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001567 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001568 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001569 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001570 log.Debugw("Retrieved logicalport from packet-in", log.Fields{
1571 "logicalPortNum": logicalPortNum,
1572 "IntfType": packetIn.IntfType,
1573 "packet": hex.EncodeToString(packetIn.Pkt),
1574 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001575 return logicalPortNum, nil
1576}
1577
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001578//GetPacketOutGemPortID returns gemPortId
1579func (f *OpenOltFlowMgr) GetPacketOutGemPortID(intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
1580 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001581 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301582
1583 f.lockCache.Lock()
1584 defer f.lockCache.Unlock()
1585 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum}
1586
1587 gemPortID, ok := f.packetInGemPort[pktInkey]
1588 if ok {
1589 log.Debugw("Found gemport for pktin key", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1590 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001591 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301592 //If gem is not found in cache try to get it from kv store, if found in kv store, update the cache and return.
1593 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(intfID, onuID, portNum)
1594 if err == nil {
1595 if gemPortID != 0 {
1596 f.packetInGemPort[pktInkey] = gemPortID
1597 log.Debugw("Found gem port from kv store and updating cache with gemport",
1598 log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1599 return gemPortID, nil
1600 }
1601 }
1602 log.Errorw("Failed to get gemport", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1603 return uint32(0), err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001604}
1605
Manikkaraj kb1d51442019-07-23 10:41:02 -04001606func installFlowOnAllGemports(
1607 f1 func(intfId uint32, onuId uint32, uniId uint32,
1608 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
1609 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32),
1610 f2 func(intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301611 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
1612 classifier map[string]interface{}, action map[string]interface{}),
Manikkaraj kb1d51442019-07-23 10:41:02 -04001613 args map[string]uint32,
1614 classifier map[string]interface{}, action map[string]interface{},
1615 logicalFlow *ofp.OfpFlowStats,
1616 gemPorts []uint32,
1617 FlowType string,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001618 vlanID ...uint32) {
1619 log.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
1620 for _, gemPortID := range gemPorts {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001621 if FlowType == HsiaFlow || FlowType == DhcpFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001622 f1(args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001623 } else if FlowType == EapolFlow {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301624 f2(args["intfId"], args["onuId"], args["uniId"], args["portNo"], logicalFlow, args["allocId"], gemPortID, vlanID[0], classifier, action)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001625 } else {
1626 log.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
1627 return
1628 }
1629 }
1630}
1631
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001632func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
1633 log.Debug("Adding trap-dhcp-of-nni-flow")
1634 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001635 classifier[PacketTagType] = DoubleTag
1636 action[TrapToHost] = true
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301637 var err error
1638 var networkInterfaceID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001639 /* We manage flowId resource pool on per PON port basis.
1640 Since this situation is tricky, as a hack, we pass the NNI port
1641 index (network_intf_id) as PON port Index for the flowId resource
1642 pool. Also, there is no ONU Id available for trapping DHCP packets
1643 on NNI port, use onu_id as -1 (invalid)
1644 ****************** CAVEAT *******************
1645 This logic works if the NNI Port Id falls within the same valid
1646 range of PON Port Ids. If this doesn't work for some OLT Vendor
1647 we need to have a re-look at this.
1648 *********************************************
1649 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001650 onuID := -1
1651 uniID := -1
1652 gemPortID := -1
1653 allocID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301654 networkInterfaceID, err = getNniIntfID(classifier, action)
1655 if err != nil {
1656 log.Error("Failed to get nniIntf ID")
1657 return
1658 }
1659
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001660 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301661 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001662 log.Debug("Flow-exists--not-re-adding")
1663 return
1664 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301665 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001666 if err != nil {
1667 log.Errorw("Flow id unavailable for DHCP traponNNI flow", log.Fields{"error": err})
1668 return
1669 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001670 var classifierProto *openoltpb2.Classifier
1671 var actionProto *openoltpb2.Action
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001672 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
1673 log.Error("Error in making classifier protobuf for dhcp trap on nni flow")
1674 return
1675 }
1676 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1677 if actionProto = makeOpenOltActionField(action); actionProto == nil {
1678 log.Error("Error in making action protobuf for dhcp trap on nni flow")
1679 return
1680 }
1681 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001682 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1683 OnuId: int32(onuID), // OnuId not required
1684 UniId: int32(uniID), // UniId not used
1685 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001686 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001687 AllocId: int32(allocID), // AllocId not used
1688 NetworkIntfId: int32(networkInterfaceID),
1689 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001690 Classifier: classifierProto,
1691 Action: actionProto,
1692 Priority: int32(logicalFlow.Priority),
1693 Cookie: logicalFlow.Cookie,
1694 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001695 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001696 log.Debug("DHCP trap on NNI flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301697 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001698 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1699 int32(onuID),
1700 int32(uniID),
1701 flowID, flowsToKVStore); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001702 log.Errorw("Error uploading DHCP DL flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1703 }
1704 }
1705 return
1706}
salmansiddiqui7ac62132019-08-22 03:58:50 +00001707
1708func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
1709 if MeterID == 0 { // This should never happen
1710 log.Error("Invalid meter id")
1711 return "", errors.New("invalid meter id")
1712 }
1713 if Dir == tp_pb.Direction_UPSTREAM {
1714 return "upstream", nil
1715 } else if Dir == tp_pb.Direction_DOWNSTREAM {
1716 return "downstream", nil
1717 }
1718 return "", nil
1719}
1720
1721func (f *OpenOltFlowMgr) checkAndAddFlow(args map[string]uint32, classifierInfo map[string]interface{},
Gamze Abakafee36392019-10-03 11:17:24 +00001722 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst *tp.TechProfile, gemPorts []uint32,
1723 TpID uint32, uni string) {
1724 var gemPort uint32
1725 intfID := args[IntfID]
1726 onuID := args[OnuID]
1727 uniID := args[UniID]
1728 portNo := args[PortNo]
1729 allocID := TpInst.UsScheduler.AllocID
salmansiddiqui7ac62132019-08-22 03:58:50 +00001730 if ipProto, ok := classifierInfo[IPProto]; ok {
1731 if ipProto.(uint32) == IPProtoDhcp {
1732 log.Info("Adding DHCP flow")
1733 if pcp, ok := classifierInfo[VlanPcp]; ok {
1734 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1735 tp_pb.Direction_UPSTREAM,
1736 pcp.(uint32))
1737 //Adding DHCP upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001738 f.addDHCPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001739 } else {
1740 //Adding DHCP upstream flow to all gemports
1741 installFlowOnAllGemports(f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, DhcpFlow)
1742 }
1743
1744 } else if ipProto == IgmpProto {
1745 log.Info("igmp flow add ignored, not implemented yet")
1746 return
1747 } else {
1748 log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
1749 return
1750 }
1751 } else if ethType, ok := classifierInfo[EthType]; ok {
1752 if ethType.(uint32) == EapEthType {
1753 log.Info("Adding EAPOL flow")
1754 var vlanID uint32
1755 if val, ok := classifierInfo[VlanVid]; ok {
1756 vlanID = (val.(uint32)) & VlanvIDMask
1757 } else {
1758 vlanID = DefaultMgmtVlan
1759 }
1760 if pcp, ok := classifierInfo[VlanPcp]; ok {
1761 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1762 tp_pb.Direction_UPSTREAM,
1763 pcp.(uint32))
1764
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301765 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID, gemPort, vlanID, classifierInfo, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001766 } else {
1767 installFlowOnAllGemports(nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, EapolFlow, vlanID)
1768 }
1769 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001770 } else if _, ok := actionInfo[PushVlan]; ok {
1771 log.Info("Adding upstream data rule")
1772 if pcp, ok := classifierInfo[VlanPcp]; ok {
1773 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1774 tp_pb.Direction_UPSTREAM,
1775 pcp.(uint32))
1776 //Adding HSIA upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001777 f.addUpstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001778 } else {
1779 //Adding HSIA upstream flow to all gemports
1780 installFlowOnAllGemports(f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1781 }
1782 } else if _, ok := actionInfo[PopVlan]; ok {
1783 log.Info("Adding Downstream data rule")
1784 if pcp, ok := classifierInfo[VlanPcp]; ok {
1785 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05001786 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001787 pcp.(uint32))
1788 //Adding HSIA downstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001789 f.addDownstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001790 } else {
1791 //Adding HSIA downstream flow to all gemports
1792 installFlowOnAllGemports(f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1793 }
1794 } else {
1795 log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
1796 return
1797 }
1798 // Send Techprofile download event to child device in go routine as it takes time
1799 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, TpID)
1800}
1801
Gamze Abakafee36392019-10-03 11:17:24 +00001802func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
1803 flowIDList := f.flowsUsedByGemPort[gemPK]
1804 if len(flowIDList) > 1 {
1805 return true
1806 }
1807 return false
1808}
1809
Girish Gowdra54934262019-11-13 14:19:55 +05301810func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
Gamze Abakafee36392019-10-03 11:17:24 +00001811 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ponIntf, onuID, uniID)
1812 tpGemPorts := tpInst.UpstreamGemPortAttributeList
1813 for _, currentGemPort := range currentGemPorts {
1814 for _, tpGemPort := range tpGemPorts {
1815 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
1816 return true, currentGemPort
1817 }
1818 }
1819 }
Girish Gowdra54934262019-11-13 14:19:55 +05301820 if tpInst.InstanceCtrl.Onu == "single-instance" {
1821 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
1822 f.resourceMgr.RemoveTechProfileIDForOnu(ponIntf, uint32(onuID), uint32(uniID), tpID)
1823 f.DeleteTechProfileInstance(ponIntf, uint32(onuID), uint32(uniID), "", tpID)
1824
1825 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
1826 // still be used on other uni ports.
1827 // So, we need to check and make sure that no other gem port is referring to the given TP ID
1828 // on any other uni port.
1829 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(tpID, ponIntf, onuID)
1830 for i := 0; i < len(tpInstances); i++ {
1831 tpI := tpInstances[i]
1832 tpGemPorts := tpI.UpstreamGemPortAttributeList
1833 for _, currentGemPort := range currentGemPorts {
1834 for _, tpGemPort := range tpGemPorts {
1835 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
1836 log.Debugw("tech-profile-is-in-use-by-gem", log.Fields{"gemPort": currentGemPort})
1837 return true, currentGemPort
1838 }
1839 }
1840 }
1841 }
1842 }
1843 log.Debug("tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00001844 return false, 0
1845}
1846
salmansiddiqui7ac62132019-08-22 03:58:50 +00001847func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07001848 for _, field := range flows.GetOfbFields(flow) {
1849 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001850 classifierInfo[EthType] = field.GetEthType()
1851 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001852 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001853 classifierInfo[IPProto] = field.GetIpProto()
1854 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001855 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001856 classifierInfo[InPort] = field.GetPort()
1857 log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001858 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05301859 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
salmansiddiqui7ac62132019-08-22 03:58:50 +00001860 log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001861 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001862 classifierInfo[VlanPcp] = field.GetVlanPcp()
1863 log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001864 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001865 classifierInfo[UDPDst] = field.GetUdpDst()
1866 log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001867 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001868 classifierInfo[UDPSrc] = field.GetUdpSrc()
1869 log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001870 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001871 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
1872 log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001873 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001874 classifierInfo[Ipv4Src] = field.GetIpv4Src()
1875 log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001876 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001877 classifierInfo[Metadata] = field.GetTableMetadata()
1878 log.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07001879 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001880 classifierInfo[TunnelID] = field.GetTunnelId()
1881 log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
1882 } else {
1883 log.Errorw("Un supported field type", log.Fields{"type": field.Type})
1884 return
1885 }
1886 }
1887}
1888
1889func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07001890 for _, action := range flows.GetActions(flow) {
1891 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001892 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001893 actionInfo[Output] = out.GetPort()
1894 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001895 } else {
1896 log.Error("Invalid output port in action")
1897 return errors.New("invalid output port in action")
1898 }
Scott Baker355d1742019-10-24 10:57:52 -07001899 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001900 actionInfo[PopVlan] = true
1901 log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001902 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001903 if out := action.GetPush(); out != nil {
1904 if tpid := out.GetEthertype(); tpid != 0x8100 {
1905 log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
1906 } else {
1907 actionInfo[PushVlan] = true
1908 actionInfo[TPID] = tpid
1909 log.Debugw("action-type-push-vlan",
1910 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
1911 }
1912 }
Scott Baker355d1742019-10-24 10:57:52 -07001913 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001914 if out := action.GetSetField(); out != nil {
1915 if field := out.GetField(); field != nil {
1916 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
1917 log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
1918 return errors.New("invalid openflow class")
1919 }
1920 /*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
1921 if ofbField := field.GetOfbField(); ofbField != nil {
1922 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
1923 if vlan := ofbField.GetVlanVid(); vlan != 0 {
1924 actionInfo[VlanVid] = vlan & 0xfff
1925 log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
1926 } else {
1927 log.Error("No Invalid vlan id in set vlan-vid action")
1928 }
1929 } else {
1930 log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
1931 }
1932 }
1933 }
1934 }
1935 } else {
1936 log.Errorw("Un supported action type", log.Fields{"type": action.Type})
1937 return errors.New("un supported action type")
1938 }
1939 }
1940 return nil
1941}
1942
1943func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001944 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001945 log.Debug("Controller bound trap flows, getting inport from tunnelid")
1946 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
1947 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001948 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001949 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07001950 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 +00001951 } else {
1952 log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1953 return errors.New("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1954 }
1955 }
1956 } else {
1957 log.Debug("Non-Controller flows, getting uniport from tunnelid")
1958 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07001959 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001960 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001961 actionInfo[Output] = uniPort
1962 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 +00001963 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001964 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 +00001965 return errors.New("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid")
1966 }
1967 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
1968 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001969 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001970 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07001971 log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[Output].(uint32),
1972 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001973 } else {
1974 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 -07001975 "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001976 return errors.New("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid")
1977 }
1978 }
1979 }
1980 return nil
1981}
Gamze Abakafee36392019-10-03 11:17:24 +00001982
Chaitrashree G S90a17952019-11-14 21:51:21 -05001983func getTpIDFromFlow(flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00001984 /* Metadata 8 bytes:
1985 Most Significant 2 Bytes = Inner VLAN
1986 Next 2 Bytes = Tech Profile ID(TPID)
1987 Least Significant 4 Bytes = Port ID
1988 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
1989 subscriber related flows.
1990 */
1991 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
1992 if metadata == 0 {
Chaitrashree G S90a17952019-11-14 21:51:21 -05001993 log.Error("metadata-is-not-present-in-flow-which-is-mandatory")
1994 return 0, errors.New("metadata-is-not-present-in-flow-which-is-mandatory")
Gamze Abakafee36392019-10-03 11:17:24 +00001995 }
1996 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001997 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00001998}
1999
2000func appendUnique(slice []uint32, item uint32) []uint32 {
2001 for _, sliceElement := range slice {
2002 if sliceElement == item {
2003 return slice
2004 }
2005 }
2006 return append(slice, item)
2007}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302008
2009// getNniIntfID gets nni intf id from the flow classifier/action
2010func getNniIntfID(classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
2011
2012 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
2013 if portType == voltha.Port_PON_OLT {
2014 intfID := IntfIDFromNniPortNum(action[Output].(uint32))
2015 log.Debugw("output Nni IntfID is", log.Fields{"intfid": intfID})
2016 return intfID, nil
2017 } else if portType == voltha.Port_ETHERNET_NNI {
2018 intfID := IntfIDFromNniPortNum(classifier[InPort].(uint32))
2019 log.Debugw("input Nni IntfID is", log.Fields{"intfid": intfID})
2020 return intfID, nil
2021 }
2022 return uint32(0), nil
2023}
2024
2025// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
2026func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32) {
2027 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort}
2028
2029 f.lockCache.Lock()
2030 defer f.lockCache.Unlock()
2031 _, ok := f.packetInGemPort[pktInkey]
2032 if ok {
2033 log.Debugw("pktin key found in cache , no need to update kv as we are assuming both will be in sync",
2034 log.Fields{"pktinkey": pktInkey, "gem": gemPort})
2035 } else {
2036 f.packetInGemPort[pktInkey] = gemPort
2037
2038 f.resourceMgr.UpdateGemPortForPktIn(pktInkey, gemPort)
2039 log.Debugw("pktin key not found in local cache updating cache and kv store", log.Fields{"pktinkey": pktInkey, "gem": gemPort})
2040 }
2041 return
2042}
2043
2044// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
2045func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(intfID uint32, onuID uint32, portNum uint32) {
2046
2047 f.lockCache.Lock()
2048 defer f.lockCache.Unlock()
2049 onugem := f.onuGemInfo[intfID]
2050 for idx, onu := range onugem {
2051 if onu.OnuID == onuID {
2052 for _, uni := range onu.UniPorts {
2053 if uni == portNum {
2054 log.Debugw("uni already in cache, no need to update cache and kv store",
2055 log.Fields{"uni": portNum})
2056 return
2057 }
2058 }
2059 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
2060 f.onuGemInfo[intfID] = onugem
2061 }
2062 }
2063 f.resourceMgr.AddUniPortToOnuInfo(intfID, onuID, portNum)
2064}