blob: f1c0639f915e80b476d0c7c3c6768ab9a1979174 [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
Gamze Abakafee36392019-10-03 11:17:24 +00001228 tpID := getTpIDFromFlow(flow)
1229
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001230 if len(updatedFlows) >= 0 {
1231 // There are still flows referencing the same flow_id.
1232 // So the flow should not be freed yet.
1233 // For ex: Case of HSIA where same flow is shared
1234 // between DS and US.
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301235 f.updateFlowInfoToKVStore(int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001236 if len(updatedFlows) == 0 {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301237 log.Debugw("Releasing flow Id to resource manager", log.Fields{"Intf": Intf, "onuId": onuID, "uniId": uniID, "flowId": flowID})
1238 f.resourceMgr.FreeFlowID(Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001239
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301240 uni := getUniPortPath(Intf, onuID, uniID)
1241 tpPath := f.getTPpath(Intf, uni, tpID)
Gamze Abakafee36392019-10-03 11:17:24 +00001242 log.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301243 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(tpID, tpPath)
Gamze Abakafee36392019-10-03 11:17:24 +00001244 if err != nil { // This should not happen, something wrong in KV backend transaction
1245 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": 20, "path": tpPath})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301246 return err
Gamze Abakafee36392019-10-03 11:17:24 +00001247 }
1248 if techprofileInst == nil {
1249 log.Errorw("Tech-profile-instance-does-not-exist-in-KV Store", log.Fields{"tpPath": tpPath})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301250 return err
Gamze Abakafee36392019-10-03 11:17:24 +00001251 }
1252
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301253 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00001254 if f.isGemPortUsedByAnotherFlow(gemPK) {
1255 flowIDs := f.flowsUsedByGemPort[gemPK]
1256 for i, flowIDinMap := range flowIDs {
1257 if flowIDinMap == flowID {
1258 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
1259 f.flowsUsedByGemPort[gemPK] = flowIDs
1260 break
1261 }
1262 }
1263 log.Debugw("Gem port id is still used by other flows", log.Fields{"gemPortID": gemPortID, "usedByFlows": flowIDs})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301264 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00001265 }
Gamze Abakafee36392019-10-03 11:17:24 +00001266 log.Debugf("Gem port id %d is not used by another flow - releasing the gem port", gemPortID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301267 f.resourceMgr.RemoveGemPortIDForOnu(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001268 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1269 // 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 +05301270 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(uint32(gemPortID), Intf)
Gamze Abakafee36392019-10-03 11:17:24 +00001271 f.onuIdsLock.Lock()
1272 delete(f.flowsUsedByGemPort, gemPK)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301273 //delete(f.onuGemPortIds, gemPK)
1274 f.resourceMgr.FreeGemPortID(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001275 f.onuIdsLock.Unlock()
1276
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301277 ok, _ := f.isTechProfileUsedByAnotherGem(Intf, uint32(onuID), uint32(uniID), techprofileInst, uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001278 if !ok {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301279 f.resourceMgr.RemoveTechProfileIDForOnu(Intf, uint32(onuID), uint32(uniID), tpID)
1280 f.RemoveSchedulerQueues(schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1281 f.RemoveSchedulerQueues(schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1282 f.DeleteTechProfileInstance(Intf, uint32(onuID), uint32(uniID), "", tpID)
1283 f.resourceMgr.FreeAllocID(Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
Gamze Abakafee36392019-10-03 11:17:24 +00001284 // TODO: Send a "Delete TechProfile" message to ONU to do its own clean up on ONU OMCI stack
1285 }
1286 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001287 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301288 return nil
1289}
1290
1291func (f *OpenOltFlowMgr) clearFlowFromResourceManager(flow *ofp.OfpFlowStats, flowDirection string) {
1292
1293 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowDirection": flowDirection, "flow": *flow})
1294 var updatedFlows []rsrcMgr.FlowInfo
1295 var flowID uint32
1296 var onuID, uniID int32
1297 classifierInfo := make(map[string]interface{})
1298
1299 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
1300 if err != nil {
1301 log.Error(err)
1302 return
1303 }
1304 onuID = int32(onu)
1305 uniID = int32(uni)
1306
1307 for _, field := range flows.GetOfbFields(flow) {
1308 if field.Type == flows.IP_PROTO {
1309 classifierInfo[IPProto] = field.GetIpProto()
1310 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
1311 }
1312 }
1313 log.Debugw("Extracted access info from flow to be deleted",
1314 log.Fields{"ponIntf": Intf, "onuID": onuID, "uniID": uniID})
1315
1316 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1317 onuID = -1
1318 uniID = -1
1319 log.Debug("Trap on nni flow set oni, uni to -1")
1320 Intf = IntfIDFromNniPortNum(inPort)
1321 }
1322 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(Intf, onuID, uniID)
1323 for _, flowID = range flowIds {
1324 flowInfo := f.resourceMgr.GetFlowIDInfo(Intf, onuID, uniID, flowID)
1325 if flowInfo == nil {
1326 log.Debugw("No FlowInfo found found in KV store",
1327 log.Fields{"Intf": Intf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1328 return
1329 }
1330 updatedFlows = nil
1331 for _, flow := range *flowInfo {
1332 updatedFlows = append(updatedFlows, flow)
1333 }
1334
1335 for i, storedFlow := range updatedFlows {
1336 if flow.Id == storedFlow.LogicalFlowID {
1337 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
1338 log.Debugw("Flow to be deleted", log.Fields{"flow": storedFlow})
1339 if ok := f.removeFlowFromDevice(&removeFlowMessage); ok {
1340 log.Debug("Flow removed from device successfully")
1341 //Remove the Flow from FlowInfo
1342 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1343 err = f.clearResources(flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
1344 flowID, flowDirection, portNum, updatedFlows)
1345 if err != nil {
1346 log.Error("Failed to clear resources for flow", log.Fields{"flow": storedFlow})
1347 return
1348 }
1349 } else {
1350 log.Error("Failed to remove flow from device")
1351 return
1352 }
1353 }
1354 }
1355 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001356}
1357
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001358//RemoveFlow removes the flow from the device
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001359func (f *OpenOltFlowMgr) RemoveFlow(flow *ofp.OfpFlowStats) {
1360 log.Debugw("Removing Flow", log.Fields{"flow": flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301361 var direction string
1362 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001363
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301364 for _, action := range flows.GetActions(flow) {
1365 if action.Type == flows.OUTPUT {
1366 if out := action.GetOutput(); out != nil {
1367 actionInfo[Output] = out.GetPort()
1368 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
1369 } else {
1370 log.Error("Invalid output port in action")
1371 return
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001372 }
1373 }
1374 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301375 if IsUpstream(actionInfo[Output].(uint32)) {
1376 direction = Upstream
1377 } else {
1378 direction = Downstream
1379 }
1380
1381 f.clearFlowFromResourceManager(flow, direction) //TODO: Take care of the limitations
1382
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001383 return
1384}
1385
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001386// AddFlow add flow to device
Manikkaraj kb1d51442019-07-23 10:41:02 -04001387func (f *OpenOltFlowMgr) AddFlow(flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001388 classifierInfo := make(map[string]interface{})
1389 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001390 var UsMeterID uint32
1391 var DsMeterID uint32
1392
1393 log.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001394 formulateClassifierInfoFromFlow(classifierInfo, flow)
1395
1396 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
1397 if err != nil {
1398 // Error logging is already done in the called function
1399 // So just return in case of error
1400 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301401 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001402
manikkaraj k17652a72019-05-06 09:06:36 -04001403 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00001404 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
1405 if err != nil {
1406 // error if any, already logged in the called function
1407 return
manikkaraj k17652a72019-05-06 09:06:36 -04001408 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001409
David K. Bainbridge82efc492019-09-04 09:57:11 -07001410 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[Output]})
1411 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00001412
Humera Kouser94d7a842019-08-25 19:04:32 -04001413 if ethType, ok := classifierInfo[EthType]; ok {
1414 if ethType.(uint32) == LldpEthType {
1415 log.Info("Adding LLDP flow")
1416 f.addLLDPFlow(flow, portNo)
1417 return
1418 }
1419 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001420 if ipProto, ok := classifierInfo[IPProto]; ok {
1421 if ipProto.(uint32) == IPProtoDhcp {
1422 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001423 if udpSrc.(uint32) == uint32(67) {
1424 log.Debug("trap-dhcp-from-nni-flow")
1425 f.addDHCPTrapFlowOnNNI(flow, classifierInfo, portNo)
1426 return
1427 }
1428 }
1429 }
1430 }
A R Karthick1f85b802019-10-11 05:06:05 +00001431
1432 f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301433 f.resourceMgr.AddUniPortToOnuInfo(intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00001434
Gamze Abakafee36392019-10-03 11:17:24 +00001435 TpID := getTpIDFromFlow(flow)
1436
salmansiddiqui7ac62132019-08-22 03:58:50 +00001437 log.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001438 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07001439 UsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001440 log.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
1441 } else {
Scott Baker355d1742019-10-24 10:57:52 -07001442 DsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001443 log.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
1444
1445 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001446 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001447}
1448
1449//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04001450func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001451
1452 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301453 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001454 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301455 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301456 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301457 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04001458
Manikkaraj kb1d51442019-07-23 10:41:02 -04001459 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001460 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
manikkaraj k17652a72019-05-06 09:06:36 -04001461 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
1462 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1463 tpDownloadMsg,
1464 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
1465 f.deviceHandler.deviceType,
1466 onuDevice.Type,
1467 onuDevice.Id,
1468 onuDevice.ProxyAddress.DeviceId, "")
1469 if sendErr != nil {
1470 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1471 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1472 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1473 return sendErr
1474 }
1475 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05301476 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301477}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001478
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301479//UpdateOnuInfo function adds onu info to cache and kvstore
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001480func (f *OpenOltFlowMgr) UpdateOnuInfo(intfID uint32, onuID uint32, serialNum string) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301481
1482 f.lockCache.Lock()
1483 defer f.lockCache.Unlock()
1484 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
1485 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
1486 if err := f.resourceMgr.AddOnuInfo(intfID, onu); err != nil {
1487 log.Errorw("failed to add onu info", log.Fields{"onu": onu})
1488 return
1489 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001490 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
1491}
1492
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301493//addGemPortToOnuInfoMap function adds GEMport to ONU map
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001494func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(intfID uint32, onuID uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301495 f.lockCache.Lock()
1496 defer f.lockCache.Unlock()
1497 onugem := f.onuGemInfo[intfID]
1498 // update the gem to the local cache as well as to kv strore
1499 for idx, onu := range onugem {
1500 if onu.OnuID == onuID {
1501 // check if gem already exists , else update the cache and kvstore
1502 for _, gem := range onu.GemPorts {
1503 if gem == gemPort {
1504 log.Debugw("Gem already in cache, no need to update cache and kv store",
1505 log.Fields{"gem": gemPort})
1506 return
1507 }
1508 }
1509 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
1510 f.onuGemInfo[intfID] = onugem
1511 }
1512 }
1513 err := f.resourceMgr.AddGemToOnuGemInfo(intfID, onuID, gemPort)
1514 if err != nil {
1515 log.Errorw("Failed to add gem to onu", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001516 return
1517 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001518}
1519
1520// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001521
1522//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
1523func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301524
1525 f.lockCache.Lock()
1526 defer f.lockCache.Unlock()
1527
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001528 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 +05301529 // get onuid from the onugem info cache
1530 onugem := f.onuGemInfo[intfID]
1531 for _, onu := range onugem {
1532 for _, gem := range onu.GemPorts {
1533 if gem == gemPortID {
1534 return onu.OnuID, nil
1535 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001536 }
1537 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001538 log.Errorw("onuid is not found", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPort": gemPortID})
1539 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 -04001540}
1541
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001542//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
1543func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001544 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001545 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001546 var err error
1547
1548 if packetIn.IntfType == "pon" {
1549 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001550 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001551 log.Errorw("Unable to get ONU ID from GEM/PON port", log.Fields{"pon port": packetIn.IntfId, "gemport": packetIn.GemportId})
1552 return logicalPortNum, err
1553 }
1554 if packetIn.PortNo != 0 {
1555 logicalPortNum = packetIn.PortNo
1556 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001557 uniID := uint32(0) // FIXME - multi-uni support
1558 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001559 }
1560 // 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 +05301561 f.UpdateGemPortForPktIn(packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001562 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001563 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001564 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001565 log.Debugw("Retrieved logicalport from packet-in", log.Fields{
1566 "logicalPortNum": logicalPortNum,
1567 "IntfType": packetIn.IntfType,
1568 "packet": hex.EncodeToString(packetIn.Pkt),
1569 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001570 return logicalPortNum, nil
1571}
1572
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001573//GetPacketOutGemPortID returns gemPortId
1574func (f *OpenOltFlowMgr) GetPacketOutGemPortID(intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
1575 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001576 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301577
1578 f.lockCache.Lock()
1579 defer f.lockCache.Unlock()
1580 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum}
1581
1582 gemPortID, ok := f.packetInGemPort[pktInkey]
1583 if ok {
1584 log.Debugw("Found gemport for pktin key", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1585 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001586 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301587 //If gem is not found in cache try to get it from kv store, if found in kv store, update the cache and return.
1588 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(intfID, onuID, portNum)
1589 if err == nil {
1590 if gemPortID != 0 {
1591 f.packetInGemPort[pktInkey] = gemPortID
1592 log.Debugw("Found gem port from kv store and updating cache with gemport",
1593 log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1594 return gemPortID, nil
1595 }
1596 }
1597 log.Errorw("Failed to get gemport", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1598 return uint32(0), err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001599}
1600
Manikkaraj kb1d51442019-07-23 10:41:02 -04001601func installFlowOnAllGemports(
1602 f1 func(intfId uint32, onuId uint32, uniId uint32,
1603 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
1604 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32),
1605 f2 func(intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301606 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
1607 classifier map[string]interface{}, action map[string]interface{}),
Manikkaraj kb1d51442019-07-23 10:41:02 -04001608 args map[string]uint32,
1609 classifier map[string]interface{}, action map[string]interface{},
1610 logicalFlow *ofp.OfpFlowStats,
1611 gemPorts []uint32,
1612 FlowType string,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001613 vlanID ...uint32) {
1614 log.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
1615 for _, gemPortID := range gemPorts {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001616 if FlowType == HsiaFlow || FlowType == DhcpFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001617 f1(args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001618 } else if FlowType == EapolFlow {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301619 f2(args["intfId"], args["onuId"], args["uniId"], args["portNo"], logicalFlow, args["allocId"], gemPortID, vlanID[0], classifier, action)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001620 } else {
1621 log.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
1622 return
1623 }
1624 }
1625}
1626
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001627func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
1628 log.Debug("Adding trap-dhcp-of-nni-flow")
1629 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001630 classifier[PacketTagType] = DoubleTag
1631 action[TrapToHost] = true
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301632 var err error
1633 var networkInterfaceID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001634 /* We manage flowId resource pool on per PON port basis.
1635 Since this situation is tricky, as a hack, we pass the NNI port
1636 index (network_intf_id) as PON port Index for the flowId resource
1637 pool. Also, there is no ONU Id available for trapping DHCP packets
1638 on NNI port, use onu_id as -1 (invalid)
1639 ****************** CAVEAT *******************
1640 This logic works if the NNI Port Id falls within the same valid
1641 range of PON Port Ids. If this doesn't work for some OLT Vendor
1642 we need to have a re-look at this.
1643 *********************************************
1644 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001645 onuID := -1
1646 uniID := -1
1647 gemPortID := -1
1648 allocID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301649 networkInterfaceID, err = getNniIntfID(classifier, action)
1650 if err != nil {
1651 log.Error("Failed to get nniIntf ID")
1652 return
1653 }
1654
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001655 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301656 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001657 log.Debug("Flow-exists--not-re-adding")
1658 return
1659 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301660 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001661 if err != nil {
1662 log.Errorw("Flow id unavailable for DHCP traponNNI flow", log.Fields{"error": err})
1663 return
1664 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001665 var classifierProto *openoltpb2.Classifier
1666 var actionProto *openoltpb2.Action
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001667 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
1668 log.Error("Error in making classifier protobuf for dhcp trap on nni flow")
1669 return
1670 }
1671 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1672 if actionProto = makeOpenOltActionField(action); actionProto == nil {
1673 log.Error("Error in making action protobuf for dhcp trap on nni flow")
1674 return
1675 }
1676 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001677 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1678 OnuId: int32(onuID), // OnuId not required
1679 UniId: int32(uniID), // UniId not used
1680 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001681 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001682 AllocId: int32(allocID), // AllocId not used
1683 NetworkIntfId: int32(networkInterfaceID),
1684 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001685 Classifier: classifierProto,
1686 Action: actionProto,
1687 Priority: int32(logicalFlow.Priority),
1688 Cookie: logicalFlow.Cookie,
1689 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001690 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001691 log.Debug("DHCP trap on NNI flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301692 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001693 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1694 int32(onuID),
1695 int32(uniID),
1696 flowID, flowsToKVStore); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001697 log.Errorw("Error uploading DHCP DL flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1698 }
1699 }
1700 return
1701}
salmansiddiqui7ac62132019-08-22 03:58:50 +00001702
1703func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
1704 if MeterID == 0 { // This should never happen
1705 log.Error("Invalid meter id")
1706 return "", errors.New("invalid meter id")
1707 }
1708 if Dir == tp_pb.Direction_UPSTREAM {
1709 return "upstream", nil
1710 } else if Dir == tp_pb.Direction_DOWNSTREAM {
1711 return "downstream", nil
1712 }
1713 return "", nil
1714}
1715
1716func (f *OpenOltFlowMgr) checkAndAddFlow(args map[string]uint32, classifierInfo map[string]interface{},
Gamze Abakafee36392019-10-03 11:17:24 +00001717 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst *tp.TechProfile, gemPorts []uint32,
1718 TpID uint32, uni string) {
1719 var gemPort uint32
1720 intfID := args[IntfID]
1721 onuID := args[OnuID]
1722 uniID := args[UniID]
1723 portNo := args[PortNo]
1724 allocID := TpInst.UsScheduler.AllocID
salmansiddiqui7ac62132019-08-22 03:58:50 +00001725 if ipProto, ok := classifierInfo[IPProto]; ok {
1726 if ipProto.(uint32) == IPProtoDhcp {
1727 log.Info("Adding DHCP flow")
1728 if pcp, ok := classifierInfo[VlanPcp]; ok {
1729 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1730 tp_pb.Direction_UPSTREAM,
1731 pcp.(uint32))
1732 //Adding DHCP upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001733 f.addDHCPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001734 } else {
1735 //Adding DHCP upstream flow to all gemports
1736 installFlowOnAllGemports(f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, DhcpFlow)
1737 }
1738
1739 } else if ipProto == IgmpProto {
1740 log.Info("igmp flow add ignored, not implemented yet")
1741 return
1742 } else {
1743 log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
1744 return
1745 }
1746 } else if ethType, ok := classifierInfo[EthType]; ok {
1747 if ethType.(uint32) == EapEthType {
1748 log.Info("Adding EAPOL flow")
1749 var vlanID uint32
1750 if val, ok := classifierInfo[VlanVid]; ok {
1751 vlanID = (val.(uint32)) & VlanvIDMask
1752 } else {
1753 vlanID = DefaultMgmtVlan
1754 }
1755 if pcp, ok := classifierInfo[VlanPcp]; ok {
1756 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1757 tp_pb.Direction_UPSTREAM,
1758 pcp.(uint32))
1759
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301760 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID, gemPort, vlanID, classifierInfo, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001761 } else {
1762 installFlowOnAllGemports(nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, EapolFlow, vlanID)
1763 }
1764 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001765 } else if _, ok := actionInfo[PushVlan]; ok {
1766 log.Info("Adding upstream data rule")
1767 if pcp, ok := classifierInfo[VlanPcp]; ok {
1768 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1769 tp_pb.Direction_UPSTREAM,
1770 pcp.(uint32))
1771 //Adding HSIA upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001772 f.addUpstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001773 } else {
1774 //Adding HSIA upstream flow to all gemports
1775 installFlowOnAllGemports(f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1776 }
1777 } else if _, ok := actionInfo[PopVlan]; ok {
1778 log.Info("Adding Downstream data rule")
1779 if pcp, ok := classifierInfo[VlanPcp]; ok {
1780 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05001781 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001782 pcp.(uint32))
1783 //Adding HSIA downstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001784 f.addDownstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001785 } else {
1786 //Adding HSIA downstream flow to all gemports
1787 installFlowOnAllGemports(f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1788 }
1789 } else {
1790 log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
1791 return
1792 }
1793 // Send Techprofile download event to child device in go routine as it takes time
1794 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, TpID)
1795}
1796
Gamze Abakafee36392019-10-03 11:17:24 +00001797func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
1798 flowIDList := f.flowsUsedByGemPort[gemPK]
1799 if len(flowIDList) > 1 {
1800 return true
1801 }
1802 return false
1803}
1804
1805func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ponIntf uint32, onuID uint32, uniID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
1806 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ponIntf, onuID, uniID)
1807 tpGemPorts := tpInst.UpstreamGemPortAttributeList
1808 for _, currentGemPort := range currentGemPorts {
1809 for _, tpGemPort := range tpGemPorts {
1810 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
1811 return true, currentGemPort
1812 }
1813 }
1814 }
1815 return false, 0
1816}
1817
salmansiddiqui7ac62132019-08-22 03:58:50 +00001818func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07001819 for _, field := range flows.GetOfbFields(flow) {
1820 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001821 classifierInfo[EthType] = field.GetEthType()
1822 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001823 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001824 classifierInfo[IPProto] = field.GetIpProto()
1825 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001826 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001827 classifierInfo[InPort] = field.GetPort()
1828 log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001829 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05301830 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
salmansiddiqui7ac62132019-08-22 03:58:50 +00001831 log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001832 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001833 classifierInfo[VlanPcp] = field.GetVlanPcp()
1834 log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001835 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001836 classifierInfo[UDPDst] = field.GetUdpDst()
1837 log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001838 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001839 classifierInfo[UDPSrc] = field.GetUdpSrc()
1840 log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001841 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001842 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
1843 log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001844 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001845 classifierInfo[Ipv4Src] = field.GetIpv4Src()
1846 log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001847 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001848 classifierInfo[Metadata] = field.GetTableMetadata()
1849 log.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07001850 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001851 classifierInfo[TunnelID] = field.GetTunnelId()
1852 log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
1853 } else {
1854 log.Errorw("Un supported field type", log.Fields{"type": field.Type})
1855 return
1856 }
1857 }
1858}
1859
1860func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07001861 for _, action := range flows.GetActions(flow) {
1862 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001863 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001864 actionInfo[Output] = out.GetPort()
1865 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001866 } else {
1867 log.Error("Invalid output port in action")
1868 return errors.New("invalid output port in action")
1869 }
Scott Baker355d1742019-10-24 10:57:52 -07001870 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001871 actionInfo[PopVlan] = true
1872 log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001873 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001874 if out := action.GetPush(); out != nil {
1875 if tpid := out.GetEthertype(); tpid != 0x8100 {
1876 log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
1877 } else {
1878 actionInfo[PushVlan] = true
1879 actionInfo[TPID] = tpid
1880 log.Debugw("action-type-push-vlan",
1881 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
1882 }
1883 }
Scott Baker355d1742019-10-24 10:57:52 -07001884 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001885 if out := action.GetSetField(); out != nil {
1886 if field := out.GetField(); field != nil {
1887 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
1888 log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
1889 return errors.New("invalid openflow class")
1890 }
1891 /*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
1892 if ofbField := field.GetOfbField(); ofbField != nil {
1893 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
1894 if vlan := ofbField.GetVlanVid(); vlan != 0 {
1895 actionInfo[VlanVid] = vlan & 0xfff
1896 log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
1897 } else {
1898 log.Error("No Invalid vlan id in set vlan-vid action")
1899 }
1900 } else {
1901 log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
1902 }
1903 }
1904 }
1905 }
1906 } else {
1907 log.Errorw("Un supported action type", log.Fields{"type": action.Type})
1908 return errors.New("un supported action type")
1909 }
1910 }
1911 return nil
1912}
1913
1914func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001915 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001916 log.Debug("Controller bound trap flows, getting inport from tunnelid")
1917 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
1918 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001919 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001920 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07001921 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 +00001922 } else {
1923 log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1924 return errors.New("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1925 }
1926 }
1927 } else {
1928 log.Debug("Non-Controller flows, getting uniport from tunnelid")
1929 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07001930 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001931 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001932 actionInfo[Output] = uniPort
1933 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 +00001934 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001935 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 +00001936 return errors.New("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid")
1937 }
1938 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
1939 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001940 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001941 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07001942 log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[Output].(uint32),
1943 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001944 } else {
1945 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 -07001946 "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001947 return errors.New("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid")
1948 }
1949 }
1950 }
1951 return nil
1952}
Gamze Abakafee36392019-10-03 11:17:24 +00001953
1954func getTpIDFromFlow(flow *ofp.OfpFlowStats) uint32 {
1955 /* Metadata 8 bytes:
1956 Most Significant 2 Bytes = Inner VLAN
1957 Next 2 Bytes = Tech Profile ID(TPID)
1958 Least Significant 4 Bytes = Port ID
1959 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
1960 subscriber related flows.
1961 */
1962 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
1963 if metadata == 0 {
1964 log.Error("Metadata is not present in flow which is mandatory")
1965 return 0
1966 }
1967 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
1968 return uint32(TpID)
1969}
1970
1971func appendUnique(slice []uint32, item uint32) []uint32 {
1972 for _, sliceElement := range slice {
1973 if sliceElement == item {
1974 return slice
1975 }
1976 }
1977 return append(slice, item)
1978}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301979
1980// getNniIntfID gets nni intf id from the flow classifier/action
1981func getNniIntfID(classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
1982
1983 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
1984 if portType == voltha.Port_PON_OLT {
1985 intfID := IntfIDFromNniPortNum(action[Output].(uint32))
1986 log.Debugw("output Nni IntfID is", log.Fields{"intfid": intfID})
1987 return intfID, nil
1988 } else if portType == voltha.Port_ETHERNET_NNI {
1989 intfID := IntfIDFromNniPortNum(classifier[InPort].(uint32))
1990 log.Debugw("input Nni IntfID is", log.Fields{"intfid": intfID})
1991 return intfID, nil
1992 }
1993 return uint32(0), nil
1994}
1995
1996// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
1997func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32) {
1998 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort}
1999
2000 f.lockCache.Lock()
2001 defer f.lockCache.Unlock()
2002 _, ok := f.packetInGemPort[pktInkey]
2003 if ok {
2004 log.Debugw("pktin key found in cache , no need to update kv as we are assuming both will be in sync",
2005 log.Fields{"pktinkey": pktInkey, "gem": gemPort})
2006 } else {
2007 f.packetInGemPort[pktInkey] = gemPort
2008
2009 f.resourceMgr.UpdateGemPortForPktIn(pktInkey, gemPort)
2010 log.Debugw("pktin key not found in local cache updating cache and kv store", log.Fields{"pktinkey": pktInkey, "gem": gemPort})
2011 }
2012 return
2013}
2014
2015// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
2016func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(intfID uint32, onuID uint32, portNum uint32) {
2017
2018 f.lockCache.Lock()
2019 defer f.lockCache.Unlock()
2020 onugem := f.onuGemInfo[intfID]
2021 for idx, onu := range onugem {
2022 if onu.OnuID == onuID {
2023 for _, uni := range onu.UniPorts {
2024 if uni == portNum {
2025 log.Debugw("uni already in cache, no need to update cache and kv store",
2026 log.Fields{"uni": portNum})
2027 return
2028 }
2029 }
2030 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
2031 f.onuGemInfo[intfID] = onugem
2032 }
2033 }
2034 f.resourceMgr.AddUniPortToOnuInfo(intfID, onuID, portNum)
2035}