blob: d39161629c3119831748e74071cab36eab338e27 [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)
451 // Check tech profile instance already exists for derived port name
salmansiddiqui7ac62132019-08-22 03:58:50 +0000452 techProfileInstance, err := f.techprofile[intfID].GetTPInstanceFromKVStore(TpID, tpPath)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400453 if err != nil { // This should not happen, something wrong in KV backend transaction
454 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": TpID, "path": tpPath})
Gamze Abakafee36392019-10-03 11:17:24 +0000455 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530456 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400457
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700458 log.Debug("Creating New TConts and Gem ports", log.Fields{"pon": intfID, "onu": onuID, "uni": uniID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530459
salmansiddiqui7ac62132019-08-22 03:58:50 +0000460 if techProfileInstance == nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530461 log.Info("Creating tech profile instance", log.Fields{"path": tpPath})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000462 techProfileInstance = f.techprofile[intfID].CreateTechProfInstance(TpID, uni, intfID)
463 if techProfileInstance == nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530464 log.Error("Tech-profile-instance-creation-failed")
Gamze Abakafee36392019-10-03 11:17:24 +0000465 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530466 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000467 f.resourceMgr.UpdateTechProfileIDForOnu(intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530468 } else {
469 log.Debugw("Tech-profile-instance-already-exist-for-given port-name", log.Fields{"uni": uni})
470 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400471 if UsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000472 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
473 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
474 if err := f.CreateSchedulerQueues(sq); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400475 log.Errorw("CreateSchedulerQueues Failed-upstream", log.Fields{"error": err, "meterID": UsMeterID})
Gamze Abakafee36392019-10-03 11:17:24 +0000476 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400477 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530478 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400479 if DsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000480 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
481 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
482 if err := f.CreateSchedulerQueues(sq); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400483 log.Errorw("CreateSchedulerQueues Failed-downstream", log.Fields{"error": err, "meterID": DsMeterID})
Gamze Abakafee36392019-10-03 11:17:24 +0000484 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400485 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530486 }
Gamze Abakafee36392019-10-03 11:17:24 +0000487
488 allocID := techProfileInstance.UsScheduler.AllocID
489 allocIDs = appendUnique(allocIDs, allocID)
490
491 for _, gem := range techProfileInstance.UpstreamGemPortAttributeList {
492 allgemPortIDs = appendUnique(allgemPortIDs, gem.GemportID)
493 gemPortIDs = append(gemPortIDs, gem.GemportID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400494 }
Gamze Abakafee36392019-10-03 11:17:24 +0000495
496 log.Debugw("Allocated Tcont and GEM ports", log.Fields{"allocIDs": allocIDs, "gemports": allgemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530497 // Send Tconts and GEM ports to KV store
Gamze Abakafee36392019-10-03 11:17:24 +0000498 f.storeTcontsGEMPortsIntoKVStore(intfID, onuID, uniID, allocIDs, allgemPortIDs)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000499 return allocID, gemPortIDs, techProfileInstance
manikkaraj kbf256be2019-03-25 00:13:48 +0530500}
501
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700502func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530503
504 log.Debugw("Storing allocated Tconts and GEM ports into KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700505 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "allocID": allocID, "gemPortIDs": gemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530506 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700507 if err := f.resourceMgr.UpdateAllocIdsForOnu(intfID, onuID, uniID, allocID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530508 log.Error("Errow while uploading allocID to KV store")
509 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700510 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(intfID, onuID, uniID, gemPortIDs); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530511 log.Error("Errow while uploading GEMports to KV store")
512 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700513 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(gemPortIDs, intfID, onuID, uniID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530514 log.Error("Errow while uploading gemtopon map to KV store")
515 }
516 log.Debug("Stored tconts and GEM into KV store successfully")
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400517 for _, gemPort := range gemPortIDs {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700518 f.addGemPortToOnuInfoMap(intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400519 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530520}
521
522func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000523 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530524 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000525 for _, intfID := range techRange.IntfIds {
526 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400527 tpCount++
salmansiddiqui7ac62132019-08-22 03:58:50 +0000528 log.Debugw("Init tech profile done", log.Fields{"intfID": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530529 }
530 }
531 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400532 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530533 log.Errorw("Error while populating techprofile",
Manikkaraj kb1d51442019-07-23 10:41:02 -0400534 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000535 return errors.New("error while populating techprofile mgrs")
manikkaraj kbf256be2019-03-25 00:13:48 +0530536 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400537 log.Infow("Populated techprofile for ponports successfully",
538 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
manikkaraj kbf256be2019-03-25 00:13:48 +0530539 return nil
540}
541
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700542func (f *OpenOltFlowMgr) addUpstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530543 portNo uint32, uplinkClassifier map[string]interface{},
544 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700545 allocID uint32, gemportID uint32) {
546 uplinkClassifier[PacketTagType] = SingleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530547 log.Debugw("Adding upstream data flow", log.Fields{"uplinkClassifier": uplinkClassifier, "uplinkAction": uplinkAction})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700548 f.addHSIAFlow(intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700549 Upstream, logicalFlow, allocID, gemportID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530550 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530551}
552
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700553func (f *OpenOltFlowMgr) addDownstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530554 portNo uint32, downlinkClassifier map[string]interface{},
555 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700556 allocID uint32, gemportID uint32) {
557 downlinkClassifier[PacketTagType] = DoubleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530558 log.Debugw("Adding downstream data flow", log.Fields{"downlinkClassifier": downlinkClassifier,
559 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400560 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
561 if vlan, exists := downlinkClassifier[VlanVid]; exists {
562 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700563 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Manikkaraj kb1d51442019-07-23 10:41:02 -0400564 if uint32(metadata.(uint64)) == MkUniPortNum(intfID, onuID, uniID) {
565 log.Infow("Ignoring DL trap device flow from core", log.Fields{"flow": logicalFlow})
566 return
567 }
568 }
569 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530570 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400571
Manikkaraj k884c1242019-04-11 16:26:42 +0530572 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700573 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400574 // vlan_vid is a uint32. must be type asserted as such or conversion fails
575 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530576 if ok {
577 downlinkAction[VlanVid] = dlClVid & 0xfff
578 } else {
579 log.Error("dl-classifier-vid-type-conversion-failed")
580 return
581 }
582
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700583 f.addHSIAFlow(intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700584 Downstream, logicalFlow, allocID, gemportID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530585}
586
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700587func (f *OpenOltFlowMgr) addHSIAFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +0530588 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700589 allocID uint32, gemPortID uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530590 var networkIntfID uint32
Manikkaraj k884c1242019-04-11 16:26:42 +0530591 /* One of the OLT platform (Broadcom BAL) requires that symmetric
592 flows require the same flow_id to be used across UL and DL.
593 Since HSIA flow is the only symmetric flow currently, we need to
594 re-use the flow_id across both direction. The 'flow_category'
595 takes priority over flow_cookie to find any available HSIA_FLOW
596 id for the ONU.
597 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700598 log.Debugw("Adding HSIA flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "classifier": classifier,
599 "action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530600 "logicalFlow": *logicalFlow})
Gamze Abakafee36392019-10-03 11:17:24 +0000601 var vlanPbit uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400602 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000603 vlanPbit = classifier[VlanPcp].(uint32)
604 log.Debugw("Found pbit in the flow", log.Fields{"VlanPbit": vlanPbit})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400605 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700606 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530607 flowID, err := f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530608 if err != nil {
609 log.Errorw("Flow id unavailable for HSIA flow", log.Fields{"direction": direction})
610 return
611 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700612 var classifierProto *openoltpb2.Classifier
613 var actionProto *openoltpb2.Action
Manikkaraj k884c1242019-04-11 16:26:42 +0530614 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
615 log.Error("Error in making classifier protobuf for hsia flow")
616 return
617 }
618 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
619 if actionProto = makeOpenOltActionField(action); actionProto == nil {
620 log.Errorw("Error in making action protobuf for hsia flow", log.Fields{"direction": direction})
621 return
622 }
623 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530624 networkIntfID, err = getNniIntfID(classifier, action)
625 if err != nil {
626 log.Error("Failed to get nniIntf ID")
627 return
628 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700629 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
630 OnuId: int32(onuID),
631 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000632 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530633 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700634 AllocId: int32(allocID),
635 NetworkIntfId: int32(networkIntfID),
636 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530637 Classifier: classifierProto,
638 Action: actionProto,
639 Priority: int32(logicalFlow.Priority),
640 Cookie: logicalFlow.Cookie,
641 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400642 if ok := f.addFlowToDevice(logicalFlow, &flow); ok {
Manikkaraj k884c1242019-04-11 16:26:42 +0530643 log.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530644 flowsToKVStore := f.getUpdatedFlowInfo(&flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
Manikkaraj k884c1242019-04-11 16:26:42 +0530645 if err := f.updateFlowInfoToKVStore(flow.AccessIntfId,
646 flow.OnuId,
647 flow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400648 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530649 log.Errorw("Error uploading HSIA flow into KV store", log.Fields{"flow": flow, "direction": direction, "error": err})
650 return
651 }
652 }
653}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700654func (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 +0530655
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700656 var dhcpFlow openoltpb2.Flow
657 var actionProto *openoltpb2.Action
658 var classifierProto *openoltpb2.Classifier
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530659 var flowID uint32
660 networkIntfID, err := getNniIntfID(classifier, action)
661 if err != nil {
662 log.Error("Failed to get nniIntf ID")
663 return
664 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530665
666 // Clear the action map
667 for k := range action {
668 delete(action, k)
669 }
670
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700671 action[TrapToHost] = true
672 classifier[UDPSrc] = uint32(68)
673 classifier[UDPDst] = uint32(67)
674 classifier[PacketTagType] = SingleTag
675 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530676
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700677 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530678
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530679 flowID, err = f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0 /*classifier[VLAN_PCP].(uint32)*/)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530680
681 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700682 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530683 return
684 }
685
686 log.Debugw("Creating UL DHCP flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID})
687
688 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
689 log.Error("Error in making classifier protobuf for ul flow")
690 return
691 }
692 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
693 if actionProto = makeOpenOltActionField(action); actionProto == nil {
694 log.Error("Error in making action protobuf for ul flow")
695 return
696 }
697
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700698 dhcpFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
699 OnuId: int32(onuID),
700 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530701 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700702 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700703 AllocId: int32(allocID),
704 NetworkIntfId: int32(networkIntfID),
705 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530706 Classifier: classifierProto,
707 Action: actionProto,
708 Priority: int32(logicalFlow.Priority),
709 Cookie: logicalFlow.Cookie,
710 PortNo: portNo}
711
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400712 if ok := f.addFlowToDevice(logicalFlow, &dhcpFlow); ok {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530713 log.Debug("DHCP UL flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530714 flowsToKVStore := f.getUpdatedFlowInfo(&dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530715 if err := f.updateFlowInfoToKVStore(dhcpFlow.AccessIntfId,
716 dhcpFlow.OnuId,
717 dhcpFlow.UniId,
718 dhcpFlow.FlowId, flowsToKVStore); err != nil {
719 log.Errorw("Error uploading DHCP UL flow into KV store", log.Fields{"flow": dhcpFlow, "error": err})
720 return
721 }
722 }
723
manikkaraj kbf256be2019-03-25 00:13:48 +0530724 return
725}
726
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700727// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530728func (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 -0700729 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 +0530730
731 uplinkClassifier := make(map[string]interface{})
732 uplinkAction := make(map[string]interface{})
733 downlinkClassifier := make(map[string]interface{})
734 downlinkAction := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700735 var upstreamFlow openoltpb2.Flow
736 var downstreamFlow openoltpb2.Flow
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530737 var networkIntfID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530738
739 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700740 uplinkClassifier[EthType] = uint32(EapEthType)
741 uplinkClassifier[PacketTagType] = SingleTag
742 uplinkClassifier[VlanVid] = vlanID
manikkaraj kbf256be2019-03-25 00:13:48 +0530743 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700744 uplinkAction[TrapToHost] = true
745 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530746 //Add Uplink EAPOL Flow
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530747 uplinkFlowID, err := f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530748 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700749 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manikkaraj k884c1242019-04-11 16:26:42 +0530750 return
manikkaraj kbf256be2019-03-25 00:13:48 +0530751 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700752 var classifierProto *openoltpb2.Classifier
753 var actionProto *openoltpb2.Action
754 log.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530755
756 if classifierProto = makeOpenOltClassifierField(uplinkClassifier); classifierProto == nil {
757 log.Error("Error in making classifier protobuf for ul flow")
758 return
759 }
760 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
761 if actionProto = makeOpenOltActionField(uplinkAction); actionProto == nil {
762 log.Error("Error in making action protobuf for ul flow")
763 return
764 }
765 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530766 networkIntfID, err = getNniIntfID(classifier, action)
767 if err != nil {
768 log.Error("Failed to get nniIntf ID")
769 return
770 }
771
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700772 upstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
773 OnuId: int32(onuID),
774 UniId: int32(uniID),
775 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700776 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700777 AllocId: int32(allocID),
778 NetworkIntfId: int32(networkIntfID),
779 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530780 Classifier: classifierProto,
781 Action: actionProto,
782 Priority: int32(logicalFlow.Priority),
783 Cookie: logicalFlow.Cookie,
784 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400785 if ok := f.addFlowToDevice(logicalFlow, &upstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530786 log.Debug("EAPOL UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400787 flowCategory := "EAPOL"
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530788 flowsToKVStore := f.getUpdatedFlowInfo(&upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
manikkaraj kbf256be2019-03-25 00:13:48 +0530789 if err := f.updateFlowInfoToKVStore(upstreamFlow.AccessIntfId,
790 upstreamFlow.OnuId,
791 upstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400792 upstreamFlow.FlowId,
793 /* lowCategory, */
794 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530795 log.Errorw("Error uploading EAPOL UL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
796 return
797 }
798 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400799 // Dummy Downstream flow due to BAL 2.6 limitation
800 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530801 /* Add Downstream EAPOL Flow, Only for first EAP flow (BAL
802 # requirement)
803 # On one of the platforms (Broadcom BAL), when same DL classifier
804 # vlan was used across multiple ONUs, eapol flow re-adds after
805 # flow delete (cases of onu reboot/disable) fails.
806 # In order to generate unique vlan, a combination of intf_id
807 # onu_id and uniId is used.
808 # uniId defaults to 0, so add 1 to it.
809 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700810 log.Debugw("Creating DL EAPOL flow with default vlan", log.Fields{"vlan": vlanID})
811 specialVlanDlFlow := 4090 - intfID*onuID*(uniID+1)
manikkaraj kbf256be2019-03-25 00:13:48 +0530812 // Assert that we do not generate invalid vlans under no condition
813 if specialVlanDlFlow <= 2 {
814 log.Fatalw("invalid-vlan-generated", log.Fields{"vlan": specialVlanDlFlow})
815 return
816 }
817 log.Debugw("specialVlanEAPOLDlFlow:", log.Fields{"dl_vlan": specialVlanDlFlow})
818 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700819 downlinkClassifier[PacketTagType] = SingleTag
Manikkaraj kb1d51442019-07-23 10:41:02 -0400820 downlinkClassifier[EthType] = uint32(EapEthType)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700821 downlinkClassifier[VlanVid] = uint32(specialVlanDlFlow)
manikkaraj kbf256be2019-03-25 00:13:48 +0530822 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700823 downlinkAction[PushVlan] = true
824 downlinkAction[VlanVid] = vlanID
825 flowStoreCookie := getFlowStoreCookie(downlinkClassifier, gemPortID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530826 downlinkFlowID, err := f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530827 if err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530828 log.Errorw("flowId unavailable for DL EAPOL",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700829 log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
manikkaraj kbf256be2019-03-25 00:13:48 +0530830 return
831 }
832 log.Debugw("Creating DL EAPOL flow",
salmansiddiqui7ac62132019-08-22 03:58:50 +0000833 log.Fields{"dl_classifier": downlinkClassifier, "dl_action": downlinkAction, "downlinkFlowID": downlinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530834 if classifierProto = makeOpenOltClassifierField(downlinkClassifier); classifierProto == nil {
835 log.Error("Error in making classifier protobuf for downlink flow")
836 return
837 }
838 if actionProto = makeOpenOltActionField(downlinkAction); actionProto == nil {
839 log.Error("Error in making action protobuf for dl flow")
840 return
841 }
842 // Downstream flow in grpc protobuf
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700843 downstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
844 OnuId: int32(onuID),
845 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000846 FlowId: downlinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700847 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700848 AllocId: int32(allocID),
849 NetworkIntfId: int32(networkIntfID),
850 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530851 Classifier: classifierProto,
852 Action: actionProto,
853 Priority: int32(logicalFlow.Priority),
854 Cookie: logicalFlow.Cookie,
855 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400856 if ok := f.addFlowToDevice(logicalFlow, &downstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530857 log.Debug("EAPOL DL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400858 flowCategory := ""
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530859 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamFlow, flowStoreCookie, flowCategory, downlinkFlowID, logicalFlow.Id)
manikkaraj kbf256be2019-03-25 00:13:48 +0530860 if err := f.updateFlowInfoToKVStore(downstreamFlow.AccessIntfId,
861 downstreamFlow.OnuId,
862 downstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400863 downstreamFlow.FlowId,
864 /* flowCategory, */
865 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530866 log.Errorw("Error uploading EAPOL DL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
867 return
868 }
869 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530870 }
871 log.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
872}
873
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700874func makeOpenOltClassifierField(classifierInfo map[string]interface{}) *openoltpb2.Classifier {
875 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -0700876
877 classifier.EthType, _ = classifierInfo[EthType].(uint32)
878 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
879 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
880 vid := vlanID & VlanvIDMask
881 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -0400882 classifier.OVid = vid
883 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530884 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700885 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
886 vid := uint32(metadata)
887 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -0400888 classifier.IVid = vid
889 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530890 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700891 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400892 if vlanPcp == 0 {
893 classifier.OPbits = VlanPCPMask
894 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700895 classifier.OPbits = vlanPcp & VlanPCPMask
Manikkaraj kb1d51442019-07-23 10:41:02 -0400896 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530897 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700898 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
899 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
900 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
901 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
902 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
903 classifier.PktTagType = pktTagType
904
905 switch pktTagType {
906 case SingleTag:
907 case DoubleTag:
908 case Untagged:
909 default:
manikkaraj kbf256be2019-03-25 00:13:48 +0530910 log.Error("Invalid tag type in classifier") // should not hit
911 return nil
912 }
913 }
914 return &classifier
915}
916
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700917func makeOpenOltActionField(actionInfo map[string]interface{}) *openoltpb2.Action {
918 var actionCmd openoltpb2.ActionCmd
919 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +0530920 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700921 if _, ok := actionInfo[PopVlan]; ok {
922 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530923 action.Cmd.RemoveOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700924 } else if _, ok := actionInfo[PushVlan]; ok {
925 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530926 action.Cmd.AddOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700927 } else if _, ok := actionInfo[TrapToHost]; ok {
928 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +0530929 } else {
930 log.Errorw("Invalid-action-field", log.Fields{"action": actionInfo})
931 return nil
932 }
933 return &action
934}
935
Manikkaraj kb1d51442019-07-23 10:41:02 -0400936func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uni string, TpID uint32) string {
937 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530938}
939
Gamze Abakafee36392019-10-03 11:17:24 +0000940// DeleteTechProfileInstances removes the tech profile instances from persistent storage
941func (f *OpenOltFlowMgr) DeleteTechProfileInstances(intfID uint32, onuID uint32, uniID uint32, sn string) error {
942 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(intfID, onuID, uniID)
Devmalya Paul495b94a2019-08-27 19:42:00 -0400943 uniPortName := fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +0000944 for _, tpID := range tpIDList {
945 if err := f.DeleteTechProfileInstance(intfID, onuID, uniID, uniPortName, tpID); err != nil {
946 log.Debugw("Failed-to-delete-tp-instance-from-kv-store", log.Fields{"tp-id": tpID, "uni-port-name": uniPortName})
947 return err
948 }
949 }
950 return nil
951}
952
953// DeleteTechProfileInstance removes the tech profile instance from persistent storage
954func (f *OpenOltFlowMgr) DeleteTechProfileInstance(intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
955 if uniPortName == "" {
956 uniPortName = fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
957 }
Devmalya Paul495b94a2019-08-27 19:42:00 -0400958 if err := f.techprofile[intfID].DeleteTechProfileInstance(tpID, uniPortName); err != nil {
959 log.Debugw("Failed-to-delete-tp-instance-from-kv-store", log.Fields{"tp-id": tpID, "uni-port-name": uniPortName})
960 return err
961 }
962 return nil
963}
964
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700965func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530966 if len(classifier) == 0 { // should never happen
967 log.Error("Invalid classfier object")
968 return 0
969 }
970 var jsonData []byte
971 var flowString string
972 var err error
973 // TODO: Do we need to marshall ??
974 if jsonData, err = json.Marshal(classifier); err != nil {
975 log.Error("Failed to encode classifier")
976 return 0
977 }
978 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700979 if gemPortID != 0 {
980 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +0530981 }
982 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700983 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +0530984 hash := big.NewInt(0)
985 hash.SetBytes(h.Sum(nil))
986 return hash.Uint64()
987}
988
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530989func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openoltpb2.Flow, flowStoreCookie uint64, flowCategory string, deviceFlowID uint32, logicalFlowID uint64) *[]rsrcMgr.FlowInfo {
990 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700991 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400992 /* For flows which trap out of the NNI, the AccessIntfId is invalid
993 (set to -1). In such cases, we need to refer to the NetworkIntfId .
994 */
995 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700996 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400997 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700998 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400999 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001000 // Get existing flows matching flowid for given subscriber from KV store
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301001 existingFlows := f.resourceMgr.GetFlowIDInfo(intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001002 if existingFlows != nil {
1003 log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001004 //for _, f := range *existingFlows {
1005 // flows = append(flows, f)
1006 //}
1007 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001008 }
1009 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 +05301010 return &flows
1011}
1012
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001013//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
1014// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
1015// var intfId uint32
1016// /* For flows which trap out of the NNI, the AccessIntfId is invalid
1017// (set to -1). In such cases, we need to refer to the NetworkIntfId .
1018// */
1019// if flow.AccessIntfId != -1 {
1020// intfId = uint32(flow.AccessIntfId)
1021// } else {
1022// intfId = uint32(flow.NetworkIntfId)
1023// }
1024// // Get existing flows matching flowid for given subscriber from KV store
1025// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
1026// if existingFlows != nil {
1027// log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
1028// for _, f := range *existingFlows {
1029// flows = append(flows, f)
1030// }
1031// }
1032// log.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
1033// return &flows
1034//}
1035
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001036func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
manikkaraj k17652a72019-05-06 09:06:36 -04001037 log.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001038 if err := f.resourceMgr.UpdateFlowIDInfo(intfID, onuID, uniID, flowID, flows); err != nil {
manikkaraj k17652a72019-05-06 09:06:36 -04001039 log.Debug("Error while Storing flow into KV store")
1040 return err
1041 }
1042 log.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +05301043 return nil
1044}
1045
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001046func (f *OpenOltFlowMgr) addFlowToDevice(logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) bool {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001047
1048 var intfID uint32
1049 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1050 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1051 */
1052 if deviceFlow.AccessIntfId != -1 {
1053 intfID = uint32(deviceFlow.AccessIntfId)
1054 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001055 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001056 intfID = uint32(deviceFlow.NetworkIntfId)
1057 }
1058
manikkaraj kbf256be2019-03-25 00:13:48 +05301059 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1060 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001061
1062 st, _ := status.FromError(err)
1063 if st.Code() == codes.AlreadyExists {
Gamze Abakafee36392019-10-03 11:17:24 +00001064 log.Debug("Flow already exists", log.Fields{"err": err, "deviceFlow": deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301065 return false
1066 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001067
1068 if err != nil {
1069 log.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": deviceFlow})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001070 f.resourceMgr.FreeFlowID(intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001071 return false
1072 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001073 f.registerFlow(logicalFlow, deviceFlow)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301074 log.Debugw("Flow added to device successfully ", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001075 return true
1076}
1077
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001078func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) bool {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001079 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1080 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1081 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001082 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
1083 log.Warnw("Can not remove flow from device since it's unreachable", log.Fields{"err": err, "deviceFlow": deviceFlow})
1084 //Assume the flow is removed
1085 return true
1086 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001087 log.Errorw("Failed to Remove flow from device", log.Fields{"err": err, "deviceFlow": deviceFlow})
1088 return false
serkant.uluderya245caba2019-09-24 23:15:29 -07001089
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001090 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001091 log.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301092 return true
1093}
1094
1095/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1096 //update core flows_proxy : flows_proxy.update('/', flows)
1097}
1098
1099func generateStoredId(flowId uint32, direction string)uint32{
1100
David K. Bainbridge82efc492019-09-04 09:57:11 -07001101 if direction == Upstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301102 log.Debug("Upstream flow shifting flowid")
1103 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001104 }else if direction == Downstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301105 log.Debug("Downstream flow not shifting flowid")
1106 return flowId
1107 }else{
1108 log.Errorw("Unrecognized direction",log.Fields{"direction": direction})
1109 return flowId
1110 }
1111}
1112
1113*/
1114
Humera Kouser94d7a842019-08-25 19:04:32 -04001115func (f *OpenOltFlowMgr) addLLDPFlow(flow *ofp.OfpFlowStats, portNo uint32) {
1116
1117 classifierInfo := make(map[string]interface{})
1118 actionInfo := make(map[string]interface{})
1119
1120 classifierInfo[EthType] = uint32(LldpEthType)
1121 classifierInfo[PacketTagType] = Untagged
1122 actionInfo[TrapToHost] = true
1123
1124 // LLDP flow is installed to trap LLDP packets on the NNI port.
1125 // We manage flow_id resource pool on per PON port basis.
1126 // Since this situation is tricky, as a hack, we pass the NNI port
1127 // index (network_intf_id) as PON port Index for the flow_id resource
1128 // pool. Also, there is no ONU Id available for trapping LLDP packets
1129 // on NNI port, use onu_id as -1 (invalid)
1130 // ****************** CAVEAT *******************
1131 // This logic works if the NNI Port Id falls within the same valid
1132 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1133 // we need to have a re-look at this.
1134 // *********************************************
1135
1136 var onuID = -1
1137 var uniID = -1
1138 var gemPortID = -1
1139
1140 var networkInterfaceID = IntfIDFromNniPortNum(portNo)
1141 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301142 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Humera Kouser94d7a842019-08-25 19:04:32 -04001143 log.Debug("Flow-exists--not-re-adding")
1144 return
1145 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301146 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001147
1148 if err != nil {
1149 log.Errorw("Flow id unavailable for LLDP traponNNI flow", log.Fields{"error": err})
1150 return
1151 }
1152 var classifierProto *openoltpb2.Classifier
1153 var actionProto *openoltpb2.Action
1154 if classifierProto = makeOpenOltClassifierField(classifierInfo); classifierProto == nil {
1155 log.Error("Error in making classifier protobuf for LLDP trap on nni flow")
1156 return
1157 }
1158 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1159 if actionProto = makeOpenOltActionField(actionInfo); actionProto == nil {
1160 log.Error("Error in making action protobuf for LLDP trap on nni flow")
1161 return
1162 }
1163 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
1164
1165 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1166 OnuId: int32(onuID), // OnuId not required
1167 UniId: int32(uniID), // UniId not used
1168 FlowId: flowID,
1169 FlowType: Downstream,
1170 NetworkIntfId: int32(networkInterfaceID),
1171 GemportId: int32(gemPortID),
1172 Classifier: classifierProto,
1173 Action: actionProto,
1174 Priority: int32(flow.Priority),
1175 Cookie: flow.Cookie,
1176 PortNo: portNo}
1177 if ok := f.addFlowToDevice(flow, &downstreamflow); ok {
1178 log.Debug("LLDP trap on NNI flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301179 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID, flow.Id)
Humera Kouser94d7a842019-08-25 19:04:32 -04001180 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1181 int32(onuID),
1182 int32(uniID),
1183 flowID, flowsToKVStore); err != nil {
1184 log.Errorw("Error uploading LLDP flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1185 }
1186 }
1187 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301188}
1189
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301190func getUniPortPath(intfID uint32, onuID int32, uniID int32) string {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001191 return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1192}
1193
1194//getOnuChildDevice to fetch onu
1195func (f *OpenOltFlowMgr) getOnuChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
1196 log.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
1197 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
1198 onuDevice := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301199 if onuDevice == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001200 log.Errorw("onu not found", log.Fields{"intfId": parentPortNo, "onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301201 return nil, errors.New("onu not found")
manikkaraj kbf256be2019-03-25 00:13:48 +05301202 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301203 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1204 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301205}
1206
1207func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001208 log.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301209 return nil
1210}
1211
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001212func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
1213 log.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301214}
1215
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001216func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001217 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001218 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001219 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001220 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001221}
1222
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301223//clearResources clears pon resources in kv store and the device
1224func (f *OpenOltFlowMgr) clearResources(flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
1225 gemPortID int32, flowID uint32, flowDirection string,
1226 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001227
Chaitrashree G S90a17952019-11-14 21:51:21 -05001228 tpID, err := getTpIDFromFlow(flow)
1229 if err != nil {
1230 log.Error("metadata-is-not-present-invalid-flow-to-process", log.Fields{"pon": Intf, "onuID": onuID, "uniID": uniID})
1231 return err
1232 }
Gamze Abakafee36392019-10-03 11:17:24 +00001233
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001234 if len(updatedFlows) >= 0 {
1235 // There are still flows referencing the same flow_id.
1236 // So the flow should not be freed yet.
1237 // For ex: Case of HSIA where same flow is shared
1238 // between DS and US.
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301239 f.updateFlowInfoToKVStore(int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001240 if len(updatedFlows) == 0 {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301241 log.Debugw("Releasing flow Id to resource manager", log.Fields{"Intf": Intf, "onuId": onuID, "uniId": uniID, "flowId": flowID})
1242 f.resourceMgr.FreeFlowID(Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001243
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301244 uni := getUniPortPath(Intf, onuID, uniID)
1245 tpPath := f.getTPpath(Intf, uni, tpID)
Gamze Abakafee36392019-10-03 11:17:24 +00001246 log.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301247 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(tpID, tpPath)
Gamze Abakafee36392019-10-03 11:17:24 +00001248 if err != nil { // This should not happen, something wrong in KV backend transaction
1249 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": 20, "path": tpPath})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301250 return err
Gamze Abakafee36392019-10-03 11:17:24 +00001251 }
1252 if techprofileInst == nil {
1253 log.Errorw("Tech-profile-instance-does-not-exist-in-KV Store", log.Fields{"tpPath": tpPath})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301254 return err
Gamze Abakafee36392019-10-03 11:17:24 +00001255 }
1256
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301257 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00001258 if f.isGemPortUsedByAnotherFlow(gemPK) {
1259 flowIDs := f.flowsUsedByGemPort[gemPK]
1260 for i, flowIDinMap := range flowIDs {
1261 if flowIDinMap == flowID {
1262 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
1263 f.flowsUsedByGemPort[gemPK] = flowIDs
1264 break
1265 }
1266 }
1267 log.Debugw("Gem port id is still used by other flows", log.Fields{"gemPortID": gemPortID, "usedByFlows": flowIDs})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301268 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00001269 }
Gamze Abakafee36392019-10-03 11:17:24 +00001270 log.Debugf("Gem port id %d is not used by another flow - releasing the gem port", gemPortID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301271 f.resourceMgr.RemoveGemPortIDForOnu(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001272 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1273 // 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 +05301274 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(uint32(gemPortID), Intf)
Gamze Abakafee36392019-10-03 11:17:24 +00001275 f.onuIdsLock.Lock()
1276 delete(f.flowsUsedByGemPort, gemPK)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301277 //delete(f.onuGemPortIds, gemPK)
1278 f.resourceMgr.FreeGemPortID(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001279 f.onuIdsLock.Unlock()
1280
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301281 ok, _ := f.isTechProfileUsedByAnotherGem(Intf, uint32(onuID), uint32(uniID), techprofileInst, uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001282 if !ok {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301283 f.resourceMgr.RemoveTechProfileIDForOnu(Intf, uint32(onuID), uint32(uniID), tpID)
1284 f.RemoveSchedulerQueues(schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1285 f.RemoveSchedulerQueues(schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1286 f.DeleteTechProfileInstance(Intf, uint32(onuID), uint32(uniID), "", tpID)
1287 f.resourceMgr.FreeAllocID(Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
Gamze Abakafee36392019-10-03 11:17:24 +00001288 // TODO: Send a "Delete TechProfile" message to ONU to do its own clean up on ONU OMCI stack
1289 }
1290 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001291 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301292 return nil
1293}
1294
1295func (f *OpenOltFlowMgr) clearFlowFromResourceManager(flow *ofp.OfpFlowStats, flowDirection string) {
1296
1297 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowDirection": flowDirection, "flow": *flow})
1298 var updatedFlows []rsrcMgr.FlowInfo
1299 var flowID uint32
1300 var onuID, uniID int32
1301 classifierInfo := make(map[string]interface{})
1302
1303 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
1304 if err != nil {
1305 log.Error(err)
1306 return
1307 }
1308 onuID = int32(onu)
1309 uniID = int32(uni)
1310
1311 for _, field := range flows.GetOfbFields(flow) {
1312 if field.Type == flows.IP_PROTO {
1313 classifierInfo[IPProto] = field.GetIpProto()
1314 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
1315 }
1316 }
1317 log.Debugw("Extracted access info from flow to be deleted",
1318 log.Fields{"ponIntf": Intf, "onuID": onuID, "uniID": uniID})
1319
1320 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1321 onuID = -1
1322 uniID = -1
1323 log.Debug("Trap on nni flow set oni, uni to -1")
1324 Intf = IntfIDFromNniPortNum(inPort)
1325 }
1326 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(Intf, onuID, uniID)
1327 for _, flowID = range flowIds {
1328 flowInfo := f.resourceMgr.GetFlowIDInfo(Intf, onuID, uniID, flowID)
1329 if flowInfo == nil {
1330 log.Debugw("No FlowInfo found found in KV store",
1331 log.Fields{"Intf": Intf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1332 return
1333 }
1334 updatedFlows = nil
1335 for _, flow := range *flowInfo {
1336 updatedFlows = append(updatedFlows, flow)
1337 }
1338
1339 for i, storedFlow := range updatedFlows {
1340 if flow.Id == storedFlow.LogicalFlowID {
1341 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
1342 log.Debugw("Flow to be deleted", log.Fields{"flow": storedFlow})
1343 if ok := f.removeFlowFromDevice(&removeFlowMessage); ok {
1344 log.Debug("Flow removed from device successfully")
1345 //Remove the Flow from FlowInfo
1346 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1347 err = f.clearResources(flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
1348 flowID, flowDirection, portNum, updatedFlows)
1349 if err != nil {
1350 log.Error("Failed to clear resources for flow", log.Fields{"flow": storedFlow})
1351 return
1352 }
1353 } else {
1354 log.Error("Failed to remove flow from device")
1355 return
1356 }
1357 }
1358 }
1359 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001360}
1361
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001362//RemoveFlow removes the flow from the device
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001363func (f *OpenOltFlowMgr) RemoveFlow(flow *ofp.OfpFlowStats) {
1364 log.Debugw("Removing Flow", log.Fields{"flow": flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301365 var direction string
1366 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001367
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301368 for _, action := range flows.GetActions(flow) {
1369 if action.Type == flows.OUTPUT {
1370 if out := action.GetOutput(); out != nil {
1371 actionInfo[Output] = out.GetPort()
1372 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
1373 } else {
1374 log.Error("Invalid output port in action")
1375 return
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001376 }
1377 }
1378 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301379 if IsUpstream(actionInfo[Output].(uint32)) {
1380 direction = Upstream
1381 } else {
1382 direction = Downstream
1383 }
1384
1385 f.clearFlowFromResourceManager(flow, direction) //TODO: Take care of the limitations
1386
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001387 return
1388}
1389
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001390// AddFlow add flow to device
Manikkaraj kb1d51442019-07-23 10:41:02 -04001391func (f *OpenOltFlowMgr) AddFlow(flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001392 classifierInfo := make(map[string]interface{})
1393 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001394 var UsMeterID uint32
1395 var DsMeterID uint32
1396
1397 log.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001398 formulateClassifierInfoFromFlow(classifierInfo, flow)
1399
1400 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
1401 if err != nil {
1402 // Error logging is already done in the called function
1403 // So just return in case of error
1404 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301405 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001406
manikkaraj k17652a72019-05-06 09:06:36 -04001407 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00001408 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
1409 if err != nil {
1410 // error if any, already logged in the called function
1411 return
manikkaraj k17652a72019-05-06 09:06:36 -04001412 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001413
David K. Bainbridge82efc492019-09-04 09:57:11 -07001414 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[Output]})
1415 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00001416
Humera Kouser94d7a842019-08-25 19:04:32 -04001417 if ethType, ok := classifierInfo[EthType]; ok {
1418 if ethType.(uint32) == LldpEthType {
1419 log.Info("Adding LLDP flow")
1420 f.addLLDPFlow(flow, portNo)
1421 return
1422 }
1423 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001424 if ipProto, ok := classifierInfo[IPProto]; ok {
1425 if ipProto.(uint32) == IPProtoDhcp {
1426 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001427 if udpSrc.(uint32) == uint32(67) {
1428 log.Debug("trap-dhcp-from-nni-flow")
1429 f.addDHCPTrapFlowOnNNI(flow, classifierInfo, portNo)
1430 return
1431 }
1432 }
1433 }
1434 }
A R Karthick1f85b802019-10-11 05:06:05 +00001435
1436 f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301437 f.resourceMgr.AddUniPortToOnuInfo(intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00001438
Chaitrashree G S90a17952019-11-14 21:51:21 -05001439 TpID, err := getTpIDFromFlow(flow)
1440 if err != nil {
1441 log.Error("metadata-is-not-present-invalid-flow-to-process", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1442 return
1443 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001444 log.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001445 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07001446 UsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001447 log.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
1448 } else {
Scott Baker355d1742019-10-24 10:57:52 -07001449 DsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001450 log.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
1451
1452 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001453 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001454}
1455
1456//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04001457func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001458
1459 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301460 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001461 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301462 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301463 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301464 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04001465
Manikkaraj kb1d51442019-07-23 10:41:02 -04001466 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001467 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
manikkaraj k17652a72019-05-06 09:06:36 -04001468 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
1469 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1470 tpDownloadMsg,
1471 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
1472 f.deviceHandler.deviceType,
1473 onuDevice.Type,
1474 onuDevice.Id,
1475 onuDevice.ProxyAddress.DeviceId, "")
1476 if sendErr != nil {
1477 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1478 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1479 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1480 return sendErr
1481 }
1482 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05301483 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301484}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001485
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301486//UpdateOnuInfo function adds onu info to cache and kvstore
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001487func (f *OpenOltFlowMgr) UpdateOnuInfo(intfID uint32, onuID uint32, serialNum string) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301488
1489 f.lockCache.Lock()
1490 defer f.lockCache.Unlock()
1491 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
1492 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
1493 if err := f.resourceMgr.AddOnuInfo(intfID, onu); err != nil {
1494 log.Errorw("failed to add onu info", log.Fields{"onu": onu})
1495 return
1496 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001497 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
1498}
1499
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301500//addGemPortToOnuInfoMap function adds GEMport to ONU map
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001501func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(intfID uint32, onuID uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301502 f.lockCache.Lock()
1503 defer f.lockCache.Unlock()
1504 onugem := f.onuGemInfo[intfID]
1505 // update the gem to the local cache as well as to kv strore
1506 for idx, onu := range onugem {
1507 if onu.OnuID == onuID {
1508 // check if gem already exists , else update the cache and kvstore
1509 for _, gem := range onu.GemPorts {
1510 if gem == gemPort {
1511 log.Debugw("Gem already in cache, no need to update cache and kv store",
1512 log.Fields{"gem": gemPort})
1513 return
1514 }
1515 }
1516 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
1517 f.onuGemInfo[intfID] = onugem
1518 }
1519 }
1520 err := f.resourceMgr.AddGemToOnuGemInfo(intfID, onuID, gemPort)
1521 if err != nil {
1522 log.Errorw("Failed to add gem to onu", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001523 return
1524 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001525}
1526
1527// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001528
1529//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
1530func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301531
1532 f.lockCache.Lock()
1533 defer f.lockCache.Unlock()
1534
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001535 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 +05301536 // get onuid from the onugem info cache
1537 onugem := f.onuGemInfo[intfID]
1538 for _, onu := range onugem {
1539 for _, gem := range onu.GemPorts {
1540 if gem == gemPortID {
1541 return onu.OnuID, nil
1542 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001543 }
1544 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001545 log.Errorw("onuid is not found", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPort": gemPortID})
1546 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 -04001547}
1548
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001549//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
1550func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001551 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001552 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001553 var err error
1554
1555 if packetIn.IntfType == "pon" {
1556 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001557 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001558 log.Errorw("Unable to get ONU ID from GEM/PON port", log.Fields{"pon port": packetIn.IntfId, "gemport": packetIn.GemportId})
1559 return logicalPortNum, err
1560 }
1561 if packetIn.PortNo != 0 {
1562 logicalPortNum = packetIn.PortNo
1563 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001564 uniID := uint32(0) // FIXME - multi-uni support
1565 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001566 }
1567 // 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 +05301568 f.UpdateGemPortForPktIn(packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001569 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001570 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001571 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001572 log.Debugw("Retrieved logicalport from packet-in", log.Fields{
1573 "logicalPortNum": logicalPortNum,
1574 "IntfType": packetIn.IntfType,
1575 "packet": hex.EncodeToString(packetIn.Pkt),
1576 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001577 return logicalPortNum, nil
1578}
1579
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001580//GetPacketOutGemPortID returns gemPortId
1581func (f *OpenOltFlowMgr) GetPacketOutGemPortID(intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
1582 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001583 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301584
1585 f.lockCache.Lock()
1586 defer f.lockCache.Unlock()
1587 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum}
1588
1589 gemPortID, ok := f.packetInGemPort[pktInkey]
1590 if ok {
1591 log.Debugw("Found gemport for pktin key", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1592 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001593 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301594 //If gem is not found in cache try to get it from kv store, if found in kv store, update the cache and return.
1595 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(intfID, onuID, portNum)
1596 if err == nil {
1597 if gemPortID != 0 {
1598 f.packetInGemPort[pktInkey] = gemPortID
1599 log.Debugw("Found gem port from kv store and updating cache with gemport",
1600 log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1601 return gemPortID, nil
1602 }
1603 }
1604 log.Errorw("Failed to get gemport", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1605 return uint32(0), err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001606}
1607
Manikkaraj kb1d51442019-07-23 10:41:02 -04001608func installFlowOnAllGemports(
1609 f1 func(intfId uint32, onuId uint32, uniId uint32,
1610 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
1611 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32),
1612 f2 func(intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301613 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
1614 classifier map[string]interface{}, action map[string]interface{}),
Manikkaraj kb1d51442019-07-23 10:41:02 -04001615 args map[string]uint32,
1616 classifier map[string]interface{}, action map[string]interface{},
1617 logicalFlow *ofp.OfpFlowStats,
1618 gemPorts []uint32,
1619 FlowType string,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001620 vlanID ...uint32) {
1621 log.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
1622 for _, gemPortID := range gemPorts {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001623 if FlowType == HsiaFlow || FlowType == DhcpFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001624 f1(args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001625 } else if FlowType == EapolFlow {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301626 f2(args["intfId"], args["onuId"], args["uniId"], args["portNo"], logicalFlow, args["allocId"], gemPortID, vlanID[0], classifier, action)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001627 } else {
1628 log.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
1629 return
1630 }
1631 }
1632}
1633
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001634func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
1635 log.Debug("Adding trap-dhcp-of-nni-flow")
1636 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001637 classifier[PacketTagType] = DoubleTag
1638 action[TrapToHost] = true
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301639 var err error
1640 var networkInterfaceID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001641 /* We manage flowId resource pool on per PON port basis.
1642 Since this situation is tricky, as a hack, we pass the NNI port
1643 index (network_intf_id) as PON port Index for the flowId resource
1644 pool. Also, there is no ONU Id available for trapping DHCP packets
1645 on NNI port, use onu_id as -1 (invalid)
1646 ****************** CAVEAT *******************
1647 This logic works if the NNI Port Id falls within the same valid
1648 range of PON Port Ids. If this doesn't work for some OLT Vendor
1649 we need to have a re-look at this.
1650 *********************************************
1651 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001652 onuID := -1
1653 uniID := -1
1654 gemPortID := -1
1655 allocID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301656 networkInterfaceID, err = getNniIntfID(classifier, action)
1657 if err != nil {
1658 log.Error("Failed to get nniIntf ID")
1659 return
1660 }
1661
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001662 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301663 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001664 log.Debug("Flow-exists--not-re-adding")
1665 return
1666 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301667 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001668 if err != nil {
1669 log.Errorw("Flow id unavailable for DHCP traponNNI flow", log.Fields{"error": err})
1670 return
1671 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001672 var classifierProto *openoltpb2.Classifier
1673 var actionProto *openoltpb2.Action
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001674 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
1675 log.Error("Error in making classifier protobuf for dhcp trap on nni flow")
1676 return
1677 }
1678 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1679 if actionProto = makeOpenOltActionField(action); actionProto == nil {
1680 log.Error("Error in making action protobuf for dhcp trap on nni flow")
1681 return
1682 }
1683 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001684 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1685 OnuId: int32(onuID), // OnuId not required
1686 UniId: int32(uniID), // UniId not used
1687 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001688 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001689 AllocId: int32(allocID), // AllocId not used
1690 NetworkIntfId: int32(networkInterfaceID),
1691 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001692 Classifier: classifierProto,
1693 Action: actionProto,
1694 Priority: int32(logicalFlow.Priority),
1695 Cookie: logicalFlow.Cookie,
1696 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001697 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001698 log.Debug("DHCP trap on NNI flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301699 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001700 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1701 int32(onuID),
1702 int32(uniID),
1703 flowID, flowsToKVStore); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001704 log.Errorw("Error uploading DHCP DL flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1705 }
1706 }
1707 return
1708}
salmansiddiqui7ac62132019-08-22 03:58:50 +00001709
1710func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
1711 if MeterID == 0 { // This should never happen
1712 log.Error("Invalid meter id")
1713 return "", errors.New("invalid meter id")
1714 }
1715 if Dir == tp_pb.Direction_UPSTREAM {
1716 return "upstream", nil
1717 } else if Dir == tp_pb.Direction_DOWNSTREAM {
1718 return "downstream", nil
1719 }
1720 return "", nil
1721}
1722
1723func (f *OpenOltFlowMgr) checkAndAddFlow(args map[string]uint32, classifierInfo map[string]interface{},
Gamze Abakafee36392019-10-03 11:17:24 +00001724 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst *tp.TechProfile, gemPorts []uint32,
1725 TpID uint32, uni string) {
1726 var gemPort uint32
1727 intfID := args[IntfID]
1728 onuID := args[OnuID]
1729 uniID := args[UniID]
1730 portNo := args[PortNo]
1731 allocID := TpInst.UsScheduler.AllocID
salmansiddiqui7ac62132019-08-22 03:58:50 +00001732 if ipProto, ok := classifierInfo[IPProto]; ok {
1733 if ipProto.(uint32) == IPProtoDhcp {
1734 log.Info("Adding DHCP flow")
1735 if pcp, ok := classifierInfo[VlanPcp]; ok {
1736 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1737 tp_pb.Direction_UPSTREAM,
1738 pcp.(uint32))
1739 //Adding DHCP upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001740 f.addDHCPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001741 } else {
1742 //Adding DHCP upstream flow to all gemports
1743 installFlowOnAllGemports(f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, DhcpFlow)
1744 }
1745
1746 } else if ipProto == IgmpProto {
1747 log.Info("igmp flow add ignored, not implemented yet")
1748 return
1749 } else {
1750 log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
1751 return
1752 }
1753 } else if ethType, ok := classifierInfo[EthType]; ok {
1754 if ethType.(uint32) == EapEthType {
1755 log.Info("Adding EAPOL flow")
1756 var vlanID uint32
1757 if val, ok := classifierInfo[VlanVid]; ok {
1758 vlanID = (val.(uint32)) & VlanvIDMask
1759 } else {
1760 vlanID = DefaultMgmtVlan
1761 }
1762 if pcp, ok := classifierInfo[VlanPcp]; ok {
1763 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1764 tp_pb.Direction_UPSTREAM,
1765 pcp.(uint32))
1766
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301767 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID, gemPort, vlanID, classifierInfo, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001768 } else {
1769 installFlowOnAllGemports(nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, EapolFlow, vlanID)
1770 }
1771 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001772 } else if _, ok := actionInfo[PushVlan]; ok {
1773 log.Info("Adding upstream data rule")
1774 if pcp, ok := classifierInfo[VlanPcp]; ok {
1775 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1776 tp_pb.Direction_UPSTREAM,
1777 pcp.(uint32))
1778 //Adding HSIA upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001779 f.addUpstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001780 } else {
1781 //Adding HSIA upstream flow to all gemports
1782 installFlowOnAllGemports(f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1783 }
1784 } else if _, ok := actionInfo[PopVlan]; ok {
1785 log.Info("Adding Downstream data rule")
1786 if pcp, ok := classifierInfo[VlanPcp]; ok {
1787 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05001788 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001789 pcp.(uint32))
1790 //Adding HSIA downstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001791 f.addDownstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001792 } else {
1793 //Adding HSIA downstream flow to all gemports
1794 installFlowOnAllGemports(f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1795 }
1796 } else {
1797 log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
1798 return
1799 }
1800 // Send Techprofile download event to child device in go routine as it takes time
1801 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, TpID)
1802}
1803
Gamze Abakafee36392019-10-03 11:17:24 +00001804func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
1805 flowIDList := f.flowsUsedByGemPort[gemPK]
1806 if len(flowIDList) > 1 {
1807 return true
1808 }
1809 return false
1810}
1811
1812func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ponIntf uint32, onuID uint32, uniID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
1813 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ponIntf, onuID, uniID)
1814 tpGemPorts := tpInst.UpstreamGemPortAttributeList
1815 for _, currentGemPort := range currentGemPorts {
1816 for _, tpGemPort := range tpGemPorts {
1817 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
1818 return true, currentGemPort
1819 }
1820 }
1821 }
1822 return false, 0
1823}
1824
salmansiddiqui7ac62132019-08-22 03:58:50 +00001825func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07001826 for _, field := range flows.GetOfbFields(flow) {
1827 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001828 classifierInfo[EthType] = field.GetEthType()
1829 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001830 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001831 classifierInfo[IPProto] = field.GetIpProto()
1832 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001833 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001834 classifierInfo[InPort] = field.GetPort()
1835 log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001836 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05301837 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
salmansiddiqui7ac62132019-08-22 03:58:50 +00001838 log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001839 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001840 classifierInfo[VlanPcp] = field.GetVlanPcp()
1841 log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001842 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001843 classifierInfo[UDPDst] = field.GetUdpDst()
1844 log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001845 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001846 classifierInfo[UDPSrc] = field.GetUdpSrc()
1847 log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001848 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001849 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
1850 log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001851 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001852 classifierInfo[Ipv4Src] = field.GetIpv4Src()
1853 log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001854 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001855 classifierInfo[Metadata] = field.GetTableMetadata()
1856 log.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07001857 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001858 classifierInfo[TunnelID] = field.GetTunnelId()
1859 log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
1860 } else {
1861 log.Errorw("Un supported field type", log.Fields{"type": field.Type})
1862 return
1863 }
1864 }
1865}
1866
1867func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07001868 for _, action := range flows.GetActions(flow) {
1869 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001870 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001871 actionInfo[Output] = out.GetPort()
1872 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001873 } else {
1874 log.Error("Invalid output port in action")
1875 return errors.New("invalid output port in action")
1876 }
Scott Baker355d1742019-10-24 10:57:52 -07001877 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001878 actionInfo[PopVlan] = true
1879 log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001880 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001881 if out := action.GetPush(); out != nil {
1882 if tpid := out.GetEthertype(); tpid != 0x8100 {
1883 log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
1884 } else {
1885 actionInfo[PushVlan] = true
1886 actionInfo[TPID] = tpid
1887 log.Debugw("action-type-push-vlan",
1888 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
1889 }
1890 }
Scott Baker355d1742019-10-24 10:57:52 -07001891 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001892 if out := action.GetSetField(); out != nil {
1893 if field := out.GetField(); field != nil {
1894 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
1895 log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
1896 return errors.New("invalid openflow class")
1897 }
1898 /*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
1899 if ofbField := field.GetOfbField(); ofbField != nil {
1900 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
1901 if vlan := ofbField.GetVlanVid(); vlan != 0 {
1902 actionInfo[VlanVid] = vlan & 0xfff
1903 log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
1904 } else {
1905 log.Error("No Invalid vlan id in set vlan-vid action")
1906 }
1907 } else {
1908 log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
1909 }
1910 }
1911 }
1912 }
1913 } else {
1914 log.Errorw("Un supported action type", log.Fields{"type": action.Type})
1915 return errors.New("un supported action type")
1916 }
1917 }
1918 return nil
1919}
1920
1921func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001922 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001923 log.Debug("Controller bound trap flows, getting inport from tunnelid")
1924 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
1925 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001926 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001927 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07001928 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 +00001929 } else {
1930 log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1931 return errors.New("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1932 }
1933 }
1934 } else {
1935 log.Debug("Non-Controller flows, getting uniport from tunnelid")
1936 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07001937 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001938 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001939 actionInfo[Output] = uniPort
1940 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 +00001941 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001942 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 +00001943 return errors.New("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid")
1944 }
1945 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
1946 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001947 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001948 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07001949 log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[Output].(uint32),
1950 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001951 } else {
1952 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 -07001953 "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001954 return errors.New("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid")
1955 }
1956 }
1957 }
1958 return nil
1959}
Gamze Abakafee36392019-10-03 11:17:24 +00001960
Chaitrashree G S90a17952019-11-14 21:51:21 -05001961func getTpIDFromFlow(flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00001962 /* Metadata 8 bytes:
1963 Most Significant 2 Bytes = Inner VLAN
1964 Next 2 Bytes = Tech Profile ID(TPID)
1965 Least Significant 4 Bytes = Port ID
1966 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
1967 subscriber related flows.
1968 */
1969 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
1970 if metadata == 0 {
Chaitrashree G S90a17952019-11-14 21:51:21 -05001971 log.Error("metadata-is-not-present-in-flow-which-is-mandatory")
1972 return 0, errors.New("metadata-is-not-present-in-flow-which-is-mandatory")
Gamze Abakafee36392019-10-03 11:17:24 +00001973 }
1974 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001975 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00001976}
1977
1978func appendUnique(slice []uint32, item uint32) []uint32 {
1979 for _, sliceElement := range slice {
1980 if sliceElement == item {
1981 return slice
1982 }
1983 }
1984 return append(slice, item)
1985}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301986
1987// getNniIntfID gets nni intf id from the flow classifier/action
1988func getNniIntfID(classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
1989
1990 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
1991 if portType == voltha.Port_PON_OLT {
1992 intfID := IntfIDFromNniPortNum(action[Output].(uint32))
1993 log.Debugw("output Nni IntfID is", log.Fields{"intfid": intfID})
1994 return intfID, nil
1995 } else if portType == voltha.Port_ETHERNET_NNI {
1996 intfID := IntfIDFromNniPortNum(classifier[InPort].(uint32))
1997 log.Debugw("input Nni IntfID is", log.Fields{"intfid": intfID})
1998 return intfID, nil
1999 }
2000 return uint32(0), nil
2001}
2002
2003// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
2004func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32) {
2005 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort}
2006
2007 f.lockCache.Lock()
2008 defer f.lockCache.Unlock()
2009 _, ok := f.packetInGemPort[pktInkey]
2010 if ok {
2011 log.Debugw("pktin key found in cache , no need to update kv as we are assuming both will be in sync",
2012 log.Fields{"pktinkey": pktInkey, "gem": gemPort})
2013 } else {
2014 f.packetInGemPort[pktInkey] = gemPort
2015
2016 f.resourceMgr.UpdateGemPortForPktIn(pktInkey, gemPort)
2017 log.Debugw("pktin key not found in local cache updating cache and kv store", log.Fields{"pktinkey": pktInkey, "gem": gemPort})
2018 }
2019 return
2020}
2021
2022// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
2023func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(intfID uint32, onuID uint32, portNum uint32) {
2024
2025 f.lockCache.Lock()
2026 defer f.lockCache.Unlock()
2027 onugem := f.onuGemInfo[intfID]
2028 for idx, onu := range onugem {
2029 if onu.OnuID == onuID {
2030 for _, uni := range onu.UniPorts {
2031 if uni == portNum {
2032 log.Debugw("uni already in cache, no need to update cache and kv store",
2033 log.Fields{"uni": portNum})
2034 return
2035 }
2036 }
2037 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
2038 f.onuGemInfo[intfID] = onugem
2039 }
2040 }
2041 f.resourceMgr.AddUniPortToOnuInfo(intfID, onuID, portNum)
2042}