blob: e3f0ccb2d6dbc2499c13d1b4ac678c1ff71bb40b [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
Gamze Abakafee36392019-10-03 11:17:24 +0000138 //IntfID constant
139 IntfID = "intfId"
140 //OnuID constant
141 OnuID = "onuId"
142 //UniID constant
143 UniID = "uniId"
144 //PortNo constant
145 PortNo = "portNo"
146 //AllocID constant
147 AllocID = "allocId"
manikkaraj kbf256be2019-03-25 00:13:48 +0530148)
149
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400150type gemPortKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700151 intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400152 gemPort uint32
153}
154
Gamze Abakafee36392019-10-03 11:17:24 +0000155type schedQueue struct {
156 direction tp_pb.Direction
157 intfID uint32
158 onuID uint32
159 uniID uint32
160 tpID uint32
161 uniPort uint32
162 tpInst *tp.TechProfile
163 meterID uint32
164 flowMetadata *voltha.FlowMetadata
165}
166
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700167//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530168type OpenOltFlowMgr struct {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000169 techprofile map[uint32]tp.TechProfileIf
Gamze Abakafee36392019-10-03 11:17:24 +0000170 deviceHandler *DeviceHandler
171 resourceMgr *rsrcMgr.OpenOltResourceMgr
Gamze Abakafee36392019-10-03 11:17:24 +0000172 onuIdsLock sync.RWMutex
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530173 flowsUsedByGemPort map[gemPortKey][]uint32 //gem port id to flow ids
174 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
175 onuGemInfo map[uint32][]rsrcMgr.OnuGemInfo //onu, gem and uni info local cache
176 lockCache sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +0530177}
178
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700179//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530180func NewFlowManager(dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
manikkaraj kbf256be2019-03-25 00:13:48 +0530181 log.Info("Initializing flow manager")
182 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530183 var err error
184 var idx uint32
185
manikkaraj kbf256be2019-03-25 00:13:48 +0530186 flowMgr.deviceHandler = dh
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530187 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000188 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530189 if err = flowMgr.populateTechProfilePerPonPort(); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530190 log.Error("Error while populating tech profile mgr\n")
191 return nil
192 }
William Kurkian740a09c2019-10-23 17:07:38 -0400193 flowMgr.onuIdsLock = sync.RWMutex{}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530194 flowMgr.flowsUsedByGemPort = make(map[gemPortKey][]uint32)
195 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
196 flowMgr.onuGemInfo = make(map[uint32][]rsrcMgr.OnuGemInfo)
197 ponPorts := rMgr.DevInfo.GetPonPorts()
198 //Load the onugem info cache from kv store on flowmanager start
199 for idx = 0; idx < ponPorts; idx++ {
200 if flowMgr.onuGemInfo[idx], err = rMgr.GetOnuGemInfo(idx); err != nil {
201 log.Error("Failed to load onu gem info cache")
202 }
203 }
204 flowMgr.lockCache = sync.RWMutex{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530205 log.Info("Initialization of flow manager success!!")
206 return &flowMgr
207}
208
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700209func (f *OpenOltFlowMgr) generateStoredFlowID(flowID uint32, direction string) (uint64, error) {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700210 if direction == Upstream {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400211 log.Debug("upstream flow, shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700212 return 0x1<<15 | uint64(flowID), nil
David K. Bainbridge82efc492019-09-04 09:57:11 -0700213 } else if direction == Downstream {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400214 log.Debug("downstream flow, not shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700215 return uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400216 } else {
217 log.Debug("Unrecognized direction")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700218 return 0, fmt.Errorf("unrecognized direction %s", direction)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400219 }
220}
221
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700222func (f *OpenOltFlowMgr) registerFlow(flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400223 log.Debug("Registering Flow for Device ", log.Fields{"flow": flowFromCore},
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700224 log.Fields{"device": f.deviceHandler.deviceID})
Gamze Abakafee36392019-10-03 11:17:24 +0000225 gemPK := gemPortKey{uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId)}
226 flowIDList, ok := f.flowsUsedByGemPort[gemPK]
227 if !ok {
228 flowIDList = []uint32{deviceFlow.FlowId}
229 }
230 flowIDList = appendUnique(flowIDList, deviceFlow.FlowId)
231 f.flowsUsedByGemPort[gemPK] = flowIDList
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400232}
233
salmansiddiqui7ac62132019-08-22 03:58:50 +0000234func (f *OpenOltFlowMgr) divideAndAddFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32,
235 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
236 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) {
Gamze Abakafee36392019-10-03 11:17:24 +0000237 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530238 var gemPorts []uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400239 var TpInst *tp.TechProfile
manikkaraj kbf256be2019-03-25 00:13:48 +0530240
Manikkaraj kb1d51442019-07-23 10:41:02 -0400241 log.Infow("Dividing flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "portNo": portNo,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000242 "classifier": classifierInfo, "action": actionInfo, "UsMeterID": UsMeterID, "DsMeterID": DsMeterID, "TpID": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400243 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
244 // is because the flow is an NNI flow and there would be no onu resources associated with it
245 // TODO: properly deal with NNI flows
Manikkaraj kb1d51442019-07-23 10:41:02 -0400246 if onuID <= 0 {
Matt Jeanneret77199612019-07-26 18:08:35 -0400247 log.Errorw("No onu id for flow", log.Fields{"portNo": portNo, "classifer": classifierInfo, "action": actionInfo})
manikkaraj kbf256be2019-03-25 00:13:48 +0530248 return
249 }
250
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530251 uni := getUniPortPath(intfID, int32(onuID), int32(uniID))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400252 log.Debugw("Uni port name", log.Fields{"uni": uni})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000253 allocID, gemPorts, TpInst = f.createTcontGemports(intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
Gamze Abakafee36392019-10-03 11:17:24 +0000254 if allocID == 0 || gemPorts == nil || TpInst == nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400255 log.Error("alloc-id-gem-ports-tp-unavailable")
256 return
257 }
258
259 /* Flows can be added specific to gemport if p-bits are received.
260 * If no pbit mentioned then adding flows for all gemports
manikkaraj kbf256be2019-03-25 00:13:48 +0530261 */
Manikkaraj kb1d51442019-07-23 10:41:02 -0400262
263 args := make(map[string]uint32)
Gamze Abakafee36392019-10-03 11:17:24 +0000264 args[IntfID] = intfID
265 args[OnuID] = onuID
266 args[UniID] = uniID
267 args[PortNo] = portNo
268 args[AllocID] = allocID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400269
Gamze Abakafee36392019-10-03 11:17:24 +0000270 f.checkAndAddFlow(args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530271}
272
salmansiddiqui7ac62132019-08-22 03:58:50 +0000273// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
Gamze Abakafee36392019-10-03 11:17:24 +0000274func (f *OpenOltFlowMgr) CreateSchedulerQueues(sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400275
Gamze Abakafee36392019-10-03 11:17:24 +0000276 log.Debugw("CreateSchedulerQueues", log.Fields{"Dir": sq.direction, "IntfID": sq.intfID,
277 "OnuID": sq.onuID, "UniID": sq.uniID, "TpID": sq.tpID, "MeterID": sq.meterID,
278 "TpInst": sq.tpInst, "flowMetadata": sq.flowMetadata})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400279
Gamze Abakafee36392019-10-03 11:17:24 +0000280 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000281 if err != nil {
282 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400283 }
284
285 /* Lets make a simple assumption that if the meter-id is present on the KV store,
286 * then the scheduler and queues configuration is applied on the OLT device
287 * in the given direction.
288 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000289
Manikkaraj kb1d51442019-07-23 10:41:02 -0400290 var SchedCfg *tp_pb.SchedulerConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000291 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400292 if err != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000293 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 -0400294 return err
295 }
296 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000297 if KvStoreMeter.MeterId == sq.meterID {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400298 log.Debug("Scheduler already created for upstream")
299 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400300 }
Gamze Abakafee36392019-10-03 11:17:24 +0000301 log.Errorw("Dynamic meter update not supported", log.Fields{"KvStoreMeterId": KvStoreMeter.MeterId, "MeterID-in-flow": sq.meterID})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000302 return errors.New("invalid-meter-id-in-flow")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400303 }
Gamze Abakafee36392019-10-03 11:17:24 +0000304 log.Debugw("Meter-does-not-exist-Creating-new", log.Fields{"MeterID": sq.meterID, "Direction": Direction})
305 if sq.direction == tp_pb.Direction_UPSTREAM {
306 SchedCfg = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
307 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
308 SchedCfg = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400309 }
310 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000311 if sq.flowMetadata != nil {
312 for _, meter := range sq.flowMetadata.Meters {
313 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400314 meterConfig = meter
315 log.Debugw("Found-meter-config-from-flowmetadata", log.Fields{"meterConfig": meterConfig})
316 break
317 }
318 }
319 } else {
320 log.Error("Flow-metadata-is-not-present-in-flow")
321 }
322 if meterConfig == nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000323 log.Errorw("Could-not-get-meterbands-from-flowMetadata", log.Fields{"flowMetadata": sq.flowMetadata,
324 "MeterID": sq.meterID})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000325 return errors.New("failed-to-get-meter-from-flowMetadata")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400326 } else if len(meterConfig.Bands) < MaxMeterBand {
Gamze Abakafee36392019-10-03 11:17:24 +0000327 log.Errorw("Invalid-number-of-bands-in-meter", log.Fields{"Bands": meterConfig.Bands, "MeterID": sq.meterID})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000328 return errors.New("invalid-number-of-bands-in-meter")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400329 }
330 cir := meterConfig.Bands[0].Rate
331 cbs := meterConfig.Bands[0].BurstSize
332 eir := meterConfig.Bands[1].Rate
333 ebs := meterConfig.Bands[1].BurstSize
334 pir := cir + eir
335 pbs := cbs + ebs
336 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
337
Gamze Abakafee36392019-10-03 11:17:24 +0000338 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Manikkaraj kb1d51442019-07-23 10:41:02 -0400339
340 log.Debugw("Sending Traffic scheduler create to device", log.Fields{"Direction": Direction, "TrafficScheds": TrafficSched})
341 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000342 IntfId: sq.intfID, OnuId: sq.onuID,
343 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400344 TrafficScheds: TrafficSched}); err != nil {
345 log.Errorw("Failed to create traffic schedulers", log.Fields{"error": err})
346 return err
347 }
348 // On receiving the CreateTrafficQueues request, the driver should create corresponding
349 // downstream queues.
Gamze Abakafee36392019-10-03 11:17:24 +0000350 trafficQueues := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400351 log.Debugw("Sending Traffic Queues create to device", log.Fields{"Direction": Direction, "TrafficQueues": trafficQueues})
352 if _, err := f.deviceHandler.Client.CreateTrafficQueues(context.Background(),
Gamze Abakafee36392019-10-03 11:17:24 +0000353 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
354 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400355 TrafficQueues: trafficQueues}); err != nil {
356 log.Errorw("Failed to create traffic queues in device", log.Fields{"error": err})
357 return err
358 }
359
salmansiddiqui7ac62132019-08-22 03:58:50 +0000360 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400361 * store the meter id on the KV store, for further reference.
362 */
Gamze Abakafee36392019-10-03 11:17:24 +0000363 if err := f.resourceMgr.UpdateMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterConfig); err != nil {
364 log.Error("Failed to update meter id for onu %d, meterid %d", sq.onuID, sq.meterID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400365 return err
366 }
367 log.Debugw("updated-meter-info into KV store successfully", log.Fields{"Direction": Direction,
368 "Meter": meterConfig})
369 return nil
370}
371
salmansiddiqui7ac62132019-08-22 03:58:50 +0000372// 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 +0000373func (f *OpenOltFlowMgr) RemoveSchedulerQueues(sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400374
375 var Direction string
376 var SchedCfg *tp_pb.SchedulerConfig
377 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000378 log.Debugw("Removing schedulers and Queues in OLT", log.Fields{"Direction": sq.direction, "IntfID": sq.intfID,
379 "OnuID": sq.onuID, "UniID": sq.uniID, "UniPort": sq.uniPort})
380 if sq.direction == tp_pb.Direction_UPSTREAM {
381 SchedCfg = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400382 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000383 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
384 SchedCfg = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400385 Direction = "downstream"
386 }
387
Gamze Abakafee36392019-10-03 11:17:24 +0000388 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400389 if err != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000390 log.Errorf("Failed to get Meter for Onu %d", sq.onuID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400391 return err
392 }
393 if KVStoreMeter == nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000394 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 -0400395 return nil
396 }
397 cir := KVStoreMeter.Bands[0].Rate
398 cbs := KVStoreMeter.Bands[0].BurstSize
399 eir := KVStoreMeter.Bands[1].Rate
400 ebs := KVStoreMeter.Bands[1].BurstSize
401 pir := cir + eir
402 pbs := cbs + ebs
403
404 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
405
Gamze Abakafee36392019-10-03 11:17:24 +0000406 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
407 TrafficQueues := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400408
409 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(context.Background(),
Gamze Abakafee36392019-10-03 11:17:24 +0000410 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
411 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400412 TrafficQueues: TrafficQueues}); err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000413 log.Errorw("Failed to remove traffic queues", log.Fields{"error": err})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400414 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400415 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000416 log.Debug("Removed traffic queues successfully")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400417 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000418 IntfId: sq.intfID, OnuId: sq.onuID,
419 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400420 TrafficScheds: TrafficSched}); err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000421 log.Errorw("failed to remove traffic schedulers", log.Fields{"error": err})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400422 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400423 }
424
salmansiddiqui7ac62132019-08-22 03:58:50 +0000425 log.Debug("Removed traffic schedulers successfully")
426
427 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400428 * delete the meter id on the KV store.
429 */
Gamze Abakafee36392019-10-03 11:17:24 +0000430 err = f.resourceMgr.RemoveMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400431 if err != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000432 log.Errorf("Failed to remove meter for onu %d, meter id %d", sq.onuID, KVStoreMeter.MeterId)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000433 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400434 }
435 log.Debugw("Removed-meter-from-KV-store successfully", log.Fields{"MeterId": KVStoreMeter.MeterId, "dir": Direction})
436 return err
437}
438
Gamze Abakafee36392019-10-03 11:17:24 +0000439// This function allocates tconts and GEM ports for an ONU
440func (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) {
441 var allocIDs []uint32
442 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530443 var gemPortIDs []uint32
Gamze Abakafee36392019-10-03 11:17:24 +0000444
445 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(intfID, onuID, uniID)
446 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400447
448 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530449
450 log.Infow("creating-new-tcont-and-gem", log.Fields{"pon": intfID, "onu": onuID, "uni": uniID})
451
Manikkaraj kb1d51442019-07-23 10:41:02 -0400452 // Check tech profile instance already exists for derived port name
Girish Gowdra54934262019-11-13 14:19:55 +0530453 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000454 if techProfileInstance == nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530455 log.Infow("tp-instance-not-found--creating-new", log.Fields{"path": tpPath})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000456 techProfileInstance = f.techprofile[intfID].CreateTechProfInstance(TpID, uni, intfID)
457 if techProfileInstance == nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530458 // This should not happen, something wrong in KV backend transaction
459 log.Error("tp-instance-create-failed")
Gamze Abakafee36392019-10-03 11:17:24 +0000460 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530461 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000462 f.resourceMgr.UpdateTechProfileIDForOnu(intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530463 } else {
464 log.Debugw("Tech-profile-instance-already-exist-for-given port-name", log.Fields{"uni": uni})
465 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400466 if UsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000467 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
468 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
469 if err := f.CreateSchedulerQueues(sq); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400470 log.Errorw("CreateSchedulerQueues Failed-upstream", log.Fields{"error": err, "meterID": UsMeterID})
Gamze Abakafee36392019-10-03 11:17:24 +0000471 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400472 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530473 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400474 if DsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000475 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
476 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
477 if err := f.CreateSchedulerQueues(sq); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400478 log.Errorw("CreateSchedulerQueues Failed-downstream", log.Fields{"error": err, "meterID": DsMeterID})
Gamze Abakafee36392019-10-03 11:17:24 +0000479 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400480 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530481 }
Gamze Abakafee36392019-10-03 11:17:24 +0000482
483 allocID := techProfileInstance.UsScheduler.AllocID
484 allocIDs = appendUnique(allocIDs, allocID)
485
486 for _, gem := range techProfileInstance.UpstreamGemPortAttributeList {
487 allgemPortIDs = appendUnique(allgemPortIDs, gem.GemportID)
488 gemPortIDs = append(gemPortIDs, gem.GemportID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400489 }
Gamze Abakafee36392019-10-03 11:17:24 +0000490
491 log.Debugw("Allocated Tcont and GEM ports", log.Fields{"allocIDs": allocIDs, "gemports": allgemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530492 // Send Tconts and GEM ports to KV store
Gamze Abakafee36392019-10-03 11:17:24 +0000493 f.storeTcontsGEMPortsIntoKVStore(intfID, onuID, uniID, allocIDs, allgemPortIDs)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000494 return allocID, gemPortIDs, techProfileInstance
manikkaraj kbf256be2019-03-25 00:13:48 +0530495}
496
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700497func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530498
499 log.Debugw("Storing allocated Tconts and GEM ports into KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700500 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "allocID": allocID, "gemPortIDs": gemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530501 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700502 if err := f.resourceMgr.UpdateAllocIdsForOnu(intfID, onuID, uniID, allocID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530503 log.Error("Errow while uploading allocID to KV store")
504 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700505 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(intfID, onuID, uniID, gemPortIDs); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530506 log.Error("Errow while uploading GEMports to KV store")
507 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700508 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(gemPortIDs, intfID, onuID, uniID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530509 log.Error("Errow while uploading gemtopon map to KV store")
510 }
511 log.Debug("Stored tconts and GEM into KV store successfully")
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400512 for _, gemPort := range gemPortIDs {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700513 f.addGemPortToOnuInfoMap(intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400514 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530515}
516
517func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000518 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530519 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000520 for _, intfID := range techRange.IntfIds {
521 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400522 tpCount++
salmansiddiqui7ac62132019-08-22 03:58:50 +0000523 log.Debugw("Init tech profile done", log.Fields{"intfID": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530524 }
525 }
526 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400527 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530528 log.Errorw("Error while populating techprofile",
Manikkaraj kb1d51442019-07-23 10:41:02 -0400529 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000530 return errors.New("error while populating techprofile mgrs")
manikkaraj kbf256be2019-03-25 00:13:48 +0530531 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400532 log.Infow("Populated techprofile for ponports successfully",
533 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
manikkaraj kbf256be2019-03-25 00:13:48 +0530534 return nil
535}
536
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700537func (f *OpenOltFlowMgr) addUpstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530538 portNo uint32, uplinkClassifier map[string]interface{},
539 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700540 allocID uint32, gemportID uint32) {
541 uplinkClassifier[PacketTagType] = SingleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530542 log.Debugw("Adding upstream data flow", log.Fields{"uplinkClassifier": uplinkClassifier, "uplinkAction": uplinkAction})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700543 f.addHSIAFlow(intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700544 Upstream, logicalFlow, allocID, gemportID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530545 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530546}
547
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700548func (f *OpenOltFlowMgr) addDownstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530549 portNo uint32, downlinkClassifier map[string]interface{},
550 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700551 allocID uint32, gemportID uint32) {
552 downlinkClassifier[PacketTagType] = DoubleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530553 log.Debugw("Adding downstream data flow", log.Fields{"downlinkClassifier": downlinkClassifier,
554 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400555 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
556 if vlan, exists := downlinkClassifier[VlanVid]; exists {
557 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700558 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Manikkaraj kb1d51442019-07-23 10:41:02 -0400559 if uint32(metadata.(uint64)) == MkUniPortNum(intfID, onuID, uniID) {
560 log.Infow("Ignoring DL trap device flow from core", log.Fields{"flow": logicalFlow})
561 return
562 }
563 }
564 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530565 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400566
Manikkaraj k884c1242019-04-11 16:26:42 +0530567 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700568 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400569 // vlan_vid is a uint32. must be type asserted as such or conversion fails
570 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530571 if ok {
572 downlinkAction[VlanVid] = dlClVid & 0xfff
573 } else {
574 log.Error("dl-classifier-vid-type-conversion-failed")
575 return
576 }
577
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700578 f.addHSIAFlow(intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700579 Downstream, logicalFlow, allocID, gemportID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530580}
581
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700582func (f *OpenOltFlowMgr) addHSIAFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +0530583 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700584 allocID uint32, gemPortID uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530585 var networkIntfID uint32
Manikkaraj k884c1242019-04-11 16:26:42 +0530586 /* One of the OLT platform (Broadcom BAL) requires that symmetric
587 flows require the same flow_id to be used across UL and DL.
588 Since HSIA flow is the only symmetric flow currently, we need to
589 re-use the flow_id across both direction. The 'flow_category'
590 takes priority over flow_cookie to find any available HSIA_FLOW
591 id for the ONU.
592 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700593 log.Debugw("Adding HSIA flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "classifier": classifier,
594 "action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530595 "logicalFlow": *logicalFlow})
Gamze Abakafee36392019-10-03 11:17:24 +0000596 var vlanPbit uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400597 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000598 vlanPbit = classifier[VlanPcp].(uint32)
599 log.Debugw("Found pbit in the flow", log.Fields{"VlanPbit": vlanPbit})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400600 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700601 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530602 flowID, err := f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530603 if err != nil {
604 log.Errorw("Flow id unavailable for HSIA flow", log.Fields{"direction": direction})
605 return
606 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700607 var classifierProto *openoltpb2.Classifier
608 var actionProto *openoltpb2.Action
Manikkaraj k884c1242019-04-11 16:26:42 +0530609 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
610 log.Error("Error in making classifier protobuf for hsia flow")
611 return
612 }
613 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
614 if actionProto = makeOpenOltActionField(action); actionProto == nil {
615 log.Errorw("Error in making action protobuf for hsia flow", log.Fields{"direction": direction})
616 return
617 }
618 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530619 networkIntfID, err = getNniIntfID(classifier, action)
620 if err != nil {
621 log.Error("Failed to get nniIntf ID")
622 return
623 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700624 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
625 OnuId: int32(onuID),
626 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000627 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530628 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700629 AllocId: int32(allocID),
630 NetworkIntfId: int32(networkIntfID),
631 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530632 Classifier: classifierProto,
633 Action: actionProto,
634 Priority: int32(logicalFlow.Priority),
635 Cookie: logicalFlow.Cookie,
636 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400637 if ok := f.addFlowToDevice(logicalFlow, &flow); ok {
Manikkaraj k884c1242019-04-11 16:26:42 +0530638 log.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530639 flowsToKVStore := f.getUpdatedFlowInfo(&flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
Manikkaraj k884c1242019-04-11 16:26:42 +0530640 if err := f.updateFlowInfoToKVStore(flow.AccessIntfId,
641 flow.OnuId,
642 flow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400643 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530644 log.Errorw("Error uploading HSIA flow into KV store", log.Fields{"flow": flow, "direction": direction, "error": err})
645 return
646 }
647 }
648}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700649func (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 +0530650
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700651 var dhcpFlow openoltpb2.Flow
652 var actionProto *openoltpb2.Action
653 var classifierProto *openoltpb2.Classifier
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530654 var flowID uint32
655 networkIntfID, err := getNniIntfID(classifier, action)
656 if err != nil {
657 log.Error("Failed to get nniIntf ID")
658 return
659 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530660
661 // Clear the action map
662 for k := range action {
663 delete(action, k)
664 }
665
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700666 action[TrapToHost] = true
667 classifier[UDPSrc] = uint32(68)
668 classifier[UDPDst] = uint32(67)
669 classifier[PacketTagType] = SingleTag
670 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530671
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700672 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530673
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530674 flowID, err = f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0 /*classifier[VLAN_PCP].(uint32)*/)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530675
676 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700677 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530678 return
679 }
680
681 log.Debugw("Creating UL DHCP flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID})
682
683 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
684 log.Error("Error in making classifier protobuf for ul flow")
685 return
686 }
687 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
688 if actionProto = makeOpenOltActionField(action); actionProto == nil {
689 log.Error("Error in making action protobuf for ul flow")
690 return
691 }
692
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700693 dhcpFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
694 OnuId: int32(onuID),
695 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530696 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700697 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700698 AllocId: int32(allocID),
699 NetworkIntfId: int32(networkIntfID),
700 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530701 Classifier: classifierProto,
702 Action: actionProto,
703 Priority: int32(logicalFlow.Priority),
704 Cookie: logicalFlow.Cookie,
705 PortNo: portNo}
706
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400707 if ok := f.addFlowToDevice(logicalFlow, &dhcpFlow); ok {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530708 log.Debug("DHCP UL flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530709 flowsToKVStore := f.getUpdatedFlowInfo(&dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530710 if err := f.updateFlowInfoToKVStore(dhcpFlow.AccessIntfId,
711 dhcpFlow.OnuId,
712 dhcpFlow.UniId,
713 dhcpFlow.FlowId, flowsToKVStore); err != nil {
714 log.Errorw("Error uploading DHCP UL flow into KV store", log.Fields{"flow": dhcpFlow, "error": err})
715 return
716 }
717 }
718
manikkaraj kbf256be2019-03-25 00:13:48 +0530719 return
720}
721
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700722// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530723func (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 -0700724 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 +0530725
726 uplinkClassifier := make(map[string]interface{})
727 uplinkAction := make(map[string]interface{})
728 downlinkClassifier := make(map[string]interface{})
729 downlinkAction := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700730 var upstreamFlow openoltpb2.Flow
731 var downstreamFlow openoltpb2.Flow
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530732 var networkIntfID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530733
734 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700735 uplinkClassifier[EthType] = uint32(EapEthType)
736 uplinkClassifier[PacketTagType] = SingleTag
737 uplinkClassifier[VlanVid] = vlanID
manikkaraj kbf256be2019-03-25 00:13:48 +0530738 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700739 uplinkAction[TrapToHost] = true
740 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530741 //Add Uplink EAPOL Flow
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530742 uplinkFlowID, err := f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530743 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700744 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manikkaraj k884c1242019-04-11 16:26:42 +0530745 return
manikkaraj kbf256be2019-03-25 00:13:48 +0530746 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700747 var classifierProto *openoltpb2.Classifier
748 var actionProto *openoltpb2.Action
749 log.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530750
751 if classifierProto = makeOpenOltClassifierField(uplinkClassifier); classifierProto == nil {
752 log.Error("Error in making classifier protobuf for ul flow")
753 return
754 }
755 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
756 if actionProto = makeOpenOltActionField(uplinkAction); actionProto == nil {
757 log.Error("Error in making action protobuf for ul flow")
758 return
759 }
760 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530761 networkIntfID, err = getNniIntfID(classifier, action)
762 if err != nil {
763 log.Error("Failed to get nniIntf ID")
764 return
765 }
766
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700767 upstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
768 OnuId: int32(onuID),
769 UniId: int32(uniID),
770 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700771 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700772 AllocId: int32(allocID),
773 NetworkIntfId: int32(networkIntfID),
774 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530775 Classifier: classifierProto,
776 Action: actionProto,
777 Priority: int32(logicalFlow.Priority),
778 Cookie: logicalFlow.Cookie,
779 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400780 if ok := f.addFlowToDevice(logicalFlow, &upstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530781 log.Debug("EAPOL UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400782 flowCategory := "EAPOL"
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530783 flowsToKVStore := f.getUpdatedFlowInfo(&upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
manikkaraj kbf256be2019-03-25 00:13:48 +0530784 if err := f.updateFlowInfoToKVStore(upstreamFlow.AccessIntfId,
785 upstreamFlow.OnuId,
786 upstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400787 upstreamFlow.FlowId,
788 /* lowCategory, */
789 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530790 log.Errorw("Error uploading EAPOL UL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
791 return
792 }
793 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400794 // Dummy Downstream flow due to BAL 2.6 limitation
795 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530796 /* Add Downstream EAPOL Flow, Only for first EAP flow (BAL
797 # requirement)
798 # On one of the platforms (Broadcom BAL), when same DL classifier
799 # vlan was used across multiple ONUs, eapol flow re-adds after
800 # flow delete (cases of onu reboot/disable) fails.
801 # In order to generate unique vlan, a combination of intf_id
802 # onu_id and uniId is used.
803 # uniId defaults to 0, so add 1 to it.
804 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700805 log.Debugw("Creating DL EAPOL flow with default vlan", log.Fields{"vlan": vlanID})
806 specialVlanDlFlow := 4090 - intfID*onuID*(uniID+1)
manikkaraj kbf256be2019-03-25 00:13:48 +0530807 // Assert that we do not generate invalid vlans under no condition
808 if specialVlanDlFlow <= 2 {
809 log.Fatalw("invalid-vlan-generated", log.Fields{"vlan": specialVlanDlFlow})
810 return
811 }
812 log.Debugw("specialVlanEAPOLDlFlow:", log.Fields{"dl_vlan": specialVlanDlFlow})
813 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700814 downlinkClassifier[PacketTagType] = SingleTag
Manikkaraj kb1d51442019-07-23 10:41:02 -0400815 downlinkClassifier[EthType] = uint32(EapEthType)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700816 downlinkClassifier[VlanVid] = uint32(specialVlanDlFlow)
manikkaraj kbf256be2019-03-25 00:13:48 +0530817 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700818 downlinkAction[PushVlan] = true
819 downlinkAction[VlanVid] = vlanID
820 flowStoreCookie := getFlowStoreCookie(downlinkClassifier, gemPortID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530821 downlinkFlowID, err := f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530822 if err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530823 log.Errorw("flowId unavailable for DL EAPOL",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700824 log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
manikkaraj kbf256be2019-03-25 00:13:48 +0530825 return
826 }
827 log.Debugw("Creating DL EAPOL flow",
salmansiddiqui7ac62132019-08-22 03:58:50 +0000828 log.Fields{"dl_classifier": downlinkClassifier, "dl_action": downlinkAction, "downlinkFlowID": downlinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530829 if classifierProto = makeOpenOltClassifierField(downlinkClassifier); classifierProto == nil {
830 log.Error("Error in making classifier protobuf for downlink flow")
831 return
832 }
833 if actionProto = makeOpenOltActionField(downlinkAction); actionProto == nil {
834 log.Error("Error in making action protobuf for dl flow")
835 return
836 }
837 // Downstream flow in grpc protobuf
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700838 downstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
839 OnuId: int32(onuID),
840 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000841 FlowId: downlinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700842 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700843 AllocId: int32(allocID),
844 NetworkIntfId: int32(networkIntfID),
845 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530846 Classifier: classifierProto,
847 Action: actionProto,
848 Priority: int32(logicalFlow.Priority),
849 Cookie: logicalFlow.Cookie,
850 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400851 if ok := f.addFlowToDevice(logicalFlow, &downstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530852 log.Debug("EAPOL DL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400853 flowCategory := ""
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530854 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamFlow, flowStoreCookie, flowCategory, downlinkFlowID, logicalFlow.Id)
manikkaraj kbf256be2019-03-25 00:13:48 +0530855 if err := f.updateFlowInfoToKVStore(downstreamFlow.AccessIntfId,
856 downstreamFlow.OnuId,
857 downstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400858 downstreamFlow.FlowId,
859 /* flowCategory, */
860 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530861 log.Errorw("Error uploading EAPOL DL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
862 return
863 }
864 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530865 }
866 log.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
867}
868
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700869func makeOpenOltClassifierField(classifierInfo map[string]interface{}) *openoltpb2.Classifier {
870 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -0700871
872 classifier.EthType, _ = classifierInfo[EthType].(uint32)
873 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
874 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
875 vid := vlanID & VlanvIDMask
876 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -0400877 classifier.OVid = vid
878 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530879 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700880 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
881 vid := uint32(metadata)
882 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -0400883 classifier.IVid = vid
884 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530885 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700886 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400887 if vlanPcp == 0 {
888 classifier.OPbits = VlanPCPMask
889 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700890 classifier.OPbits = vlanPcp & VlanPCPMask
Manikkaraj kb1d51442019-07-23 10:41:02 -0400891 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530892 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700893 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
894 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
895 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
896 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
897 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
898 classifier.PktTagType = pktTagType
899
900 switch pktTagType {
901 case SingleTag:
902 case DoubleTag:
903 case Untagged:
904 default:
manikkaraj kbf256be2019-03-25 00:13:48 +0530905 log.Error("Invalid tag type in classifier") // should not hit
906 return nil
907 }
908 }
909 return &classifier
910}
911
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700912func makeOpenOltActionField(actionInfo map[string]interface{}) *openoltpb2.Action {
913 var actionCmd openoltpb2.ActionCmd
914 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +0530915 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700916 if _, ok := actionInfo[PopVlan]; ok {
917 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530918 action.Cmd.RemoveOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700919 } else if _, ok := actionInfo[PushVlan]; ok {
920 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530921 action.Cmd.AddOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700922 } else if _, ok := actionInfo[TrapToHost]; ok {
923 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +0530924 } else {
925 log.Errorw("Invalid-action-field", log.Fields{"action": actionInfo})
926 return nil
927 }
928 return &action
929}
930
Manikkaraj kb1d51442019-07-23 10:41:02 -0400931func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uni string, TpID uint32) string {
932 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530933}
934
Gamze Abakafee36392019-10-03 11:17:24 +0000935// DeleteTechProfileInstances removes the tech profile instances from persistent storage
936func (f *OpenOltFlowMgr) DeleteTechProfileInstances(intfID uint32, onuID uint32, uniID uint32, sn string) error {
937 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(intfID, onuID, uniID)
Devmalya Paul495b94a2019-08-27 19:42:00 -0400938 uniPortName := fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +0000939 for _, tpID := range tpIDList {
940 if err := f.DeleteTechProfileInstance(intfID, onuID, uniID, uniPortName, tpID); err != nil {
941 log.Debugw("Failed-to-delete-tp-instance-from-kv-store", log.Fields{"tp-id": tpID, "uni-port-name": uniPortName})
Girish Gowdra54934262019-11-13 14:19:55 +0530942 // return err
943 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +0000944 }
945 }
946 return nil
947}
948
949// DeleteTechProfileInstance removes the tech profile instance from persistent storage
950func (f *OpenOltFlowMgr) DeleteTechProfileInstance(intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
951 if uniPortName == "" {
952 uniPortName = fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
953 }
Devmalya Paul495b94a2019-08-27 19:42:00 -0400954 if err := f.techprofile[intfID].DeleteTechProfileInstance(tpID, uniPortName); err != nil {
955 log.Debugw("Failed-to-delete-tp-instance-from-kv-store", log.Fields{"tp-id": tpID, "uni-port-name": uniPortName})
956 return err
957 }
958 return nil
959}
960
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700961func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530962 if len(classifier) == 0 { // should never happen
963 log.Error("Invalid classfier object")
964 return 0
965 }
966 var jsonData []byte
967 var flowString string
968 var err error
969 // TODO: Do we need to marshall ??
970 if jsonData, err = json.Marshal(classifier); err != nil {
971 log.Error("Failed to encode classifier")
972 return 0
973 }
974 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700975 if gemPortID != 0 {
976 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +0530977 }
978 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700979 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +0530980 hash := big.NewInt(0)
981 hash.SetBytes(h.Sum(nil))
982 return hash.Uint64()
983}
984
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530985func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openoltpb2.Flow, flowStoreCookie uint64, flowCategory string, deviceFlowID uint32, logicalFlowID uint64) *[]rsrcMgr.FlowInfo {
986 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700987 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400988 /* For flows which trap out of the NNI, the AccessIntfId is invalid
989 (set to -1). In such cases, we need to refer to the NetworkIntfId .
990 */
991 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700992 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400993 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700994 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400995 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700996 // Get existing flows matching flowid for given subscriber from KV store
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530997 existingFlows := f.resourceMgr.GetFlowIDInfo(intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -0400998 if existingFlows != nil {
999 log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001000 //for _, f := range *existingFlows {
1001 // flows = append(flows, f)
1002 //}
1003 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001004 }
1005 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 +05301006 return &flows
1007}
1008
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001009//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
1010// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
1011// var intfId uint32
1012// /* For flows which trap out of the NNI, the AccessIntfId is invalid
1013// (set to -1). In such cases, we need to refer to the NetworkIntfId .
1014// */
1015// if flow.AccessIntfId != -1 {
1016// intfId = uint32(flow.AccessIntfId)
1017// } else {
1018// intfId = uint32(flow.NetworkIntfId)
1019// }
1020// // Get existing flows matching flowid for given subscriber from KV store
1021// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
1022// if existingFlows != nil {
1023// log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
1024// for _, f := range *existingFlows {
1025// flows = append(flows, f)
1026// }
1027// }
1028// log.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
1029// return &flows
1030//}
1031
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001032func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
manikkaraj k17652a72019-05-06 09:06:36 -04001033 log.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001034 if err := f.resourceMgr.UpdateFlowIDInfo(intfID, onuID, uniID, flowID, flows); err != nil {
manikkaraj k17652a72019-05-06 09:06:36 -04001035 log.Debug("Error while Storing flow into KV store")
1036 return err
1037 }
1038 log.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +05301039 return nil
1040}
1041
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001042func (f *OpenOltFlowMgr) addFlowToDevice(logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) bool {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001043
1044 var intfID uint32
1045 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1046 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1047 */
1048 if deviceFlow.AccessIntfId != -1 {
1049 intfID = uint32(deviceFlow.AccessIntfId)
1050 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001051 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001052 intfID = uint32(deviceFlow.NetworkIntfId)
1053 }
1054
manikkaraj kbf256be2019-03-25 00:13:48 +05301055 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1056 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001057
1058 st, _ := status.FromError(err)
1059 if st.Code() == codes.AlreadyExists {
Gamze Abakafee36392019-10-03 11:17:24 +00001060 log.Debug("Flow already exists", log.Fields{"err": err, "deviceFlow": deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301061 return false
1062 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001063
1064 if err != nil {
1065 log.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": deviceFlow})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001066 f.resourceMgr.FreeFlowID(intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001067 return false
1068 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001069 f.registerFlow(logicalFlow, deviceFlow)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301070 log.Debugw("Flow added to device successfully ", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001071 return true
1072}
1073
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001074func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) bool {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001075 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1076 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1077 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001078 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
1079 log.Warnw("Can not remove flow from device since it's unreachable", log.Fields{"err": err, "deviceFlow": deviceFlow})
1080 //Assume the flow is removed
1081 return true
1082 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001083 log.Errorw("Failed to Remove flow from device", log.Fields{"err": err, "deviceFlow": deviceFlow})
1084 return false
serkant.uluderya245caba2019-09-24 23:15:29 -07001085
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001086 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001087 log.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301088 return true
1089}
1090
1091/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1092 //update core flows_proxy : flows_proxy.update('/', flows)
1093}
1094
1095func generateStoredId(flowId uint32, direction string)uint32{
1096
David K. Bainbridge82efc492019-09-04 09:57:11 -07001097 if direction == Upstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301098 log.Debug("Upstream flow shifting flowid")
1099 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001100 }else if direction == Downstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301101 log.Debug("Downstream flow not shifting flowid")
1102 return flowId
1103 }else{
1104 log.Errorw("Unrecognized direction",log.Fields{"direction": direction})
1105 return flowId
1106 }
1107}
1108
1109*/
1110
Humera Kouser94d7a842019-08-25 19:04:32 -04001111func (f *OpenOltFlowMgr) addLLDPFlow(flow *ofp.OfpFlowStats, portNo uint32) {
1112
1113 classifierInfo := make(map[string]interface{})
1114 actionInfo := make(map[string]interface{})
1115
1116 classifierInfo[EthType] = uint32(LldpEthType)
1117 classifierInfo[PacketTagType] = Untagged
1118 actionInfo[TrapToHost] = true
1119
1120 // LLDP flow is installed to trap LLDP packets on the NNI port.
1121 // We manage flow_id resource pool on per PON port basis.
1122 // Since this situation is tricky, as a hack, we pass the NNI port
1123 // index (network_intf_id) as PON port Index for the flow_id resource
1124 // pool. Also, there is no ONU Id available for trapping LLDP packets
1125 // on NNI port, use onu_id as -1 (invalid)
1126 // ****************** CAVEAT *******************
1127 // This logic works if the NNI Port Id falls within the same valid
1128 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1129 // we need to have a re-look at this.
1130 // *********************************************
1131
1132 var onuID = -1
1133 var uniID = -1
1134 var gemPortID = -1
1135
1136 var networkInterfaceID = IntfIDFromNniPortNum(portNo)
1137 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301138 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Humera Kouser94d7a842019-08-25 19:04:32 -04001139 log.Debug("Flow-exists--not-re-adding")
1140 return
1141 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301142 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001143
1144 if err != nil {
1145 log.Errorw("Flow id unavailable for LLDP traponNNI flow", log.Fields{"error": err})
1146 return
1147 }
1148 var classifierProto *openoltpb2.Classifier
1149 var actionProto *openoltpb2.Action
1150 if classifierProto = makeOpenOltClassifierField(classifierInfo); classifierProto == nil {
1151 log.Error("Error in making classifier protobuf for LLDP trap on nni flow")
1152 return
1153 }
1154 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1155 if actionProto = makeOpenOltActionField(actionInfo); actionProto == nil {
1156 log.Error("Error in making action protobuf for LLDP trap on nni flow")
1157 return
1158 }
1159 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
1160
1161 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1162 OnuId: int32(onuID), // OnuId not required
1163 UniId: int32(uniID), // UniId not used
1164 FlowId: flowID,
1165 FlowType: Downstream,
1166 NetworkIntfId: int32(networkInterfaceID),
1167 GemportId: int32(gemPortID),
1168 Classifier: classifierProto,
1169 Action: actionProto,
1170 Priority: int32(flow.Priority),
1171 Cookie: flow.Cookie,
1172 PortNo: portNo}
1173 if ok := f.addFlowToDevice(flow, &downstreamflow); ok {
1174 log.Debug("LLDP trap on NNI flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301175 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID, flow.Id)
Humera Kouser94d7a842019-08-25 19:04:32 -04001176 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1177 int32(onuID),
1178 int32(uniID),
1179 flowID, flowsToKVStore); err != nil {
1180 log.Errorw("Error uploading LLDP flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1181 }
1182 }
1183 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301184}
1185
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301186func getUniPortPath(intfID uint32, onuID int32, uniID int32) string {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001187 return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1188}
1189
1190//getOnuChildDevice to fetch onu
1191func (f *OpenOltFlowMgr) getOnuChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
1192 log.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
1193 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
1194 onuDevice := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301195 if onuDevice == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001196 log.Errorw("onu not found", log.Fields{"intfId": parentPortNo, "onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301197 return nil, errors.New("onu not found")
manikkaraj kbf256be2019-03-25 00:13:48 +05301198 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301199 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1200 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301201}
1202
1203func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001204 log.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301205 return nil
1206}
1207
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001208func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
1209 log.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301210}
1211
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001212func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001213 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001214 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001215 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001216 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001217}
1218
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301219//clearResources clears pon resources in kv store and the device
1220func (f *OpenOltFlowMgr) clearResources(flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
1221 gemPortID int32, flowID uint32, flowDirection string,
1222 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001223
Chaitrashree G S90a17952019-11-14 21:51:21 -05001224 tpID, err := getTpIDFromFlow(flow)
1225 if err != nil {
1226 log.Error("metadata-is-not-present-invalid-flow-to-process", log.Fields{"pon": Intf, "onuID": onuID, "uniID": uniID})
1227 return err
1228 }
Gamze Abakafee36392019-10-03 11:17:24 +00001229
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
Girish Gowdra54934262019-11-13 14:19:55 +05301277 ok, _ := f.isTechProfileUsedByAnotherGem(Intf, uint32(onuID), uint32(uniID), tpID, 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
Chaitrashree G S90a17952019-11-14 21:51:21 -05001435 TpID, err := getTpIDFromFlow(flow)
1436 if err != nil {
1437 log.Error("metadata-is-not-present-invalid-flow-to-process", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1438 return
1439 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001440 log.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001441 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07001442 UsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001443 log.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
1444 } else {
Scott Baker355d1742019-10-24 10:57:52 -07001445 DsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001446 log.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
1447
1448 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001449 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001450}
1451
1452//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04001453func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001454
1455 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301456 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001457 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301458 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301459 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301460 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04001461
Manikkaraj kb1d51442019-07-23 10:41:02 -04001462 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001463 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
manikkaraj k17652a72019-05-06 09:06:36 -04001464 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
1465 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1466 tpDownloadMsg,
1467 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
1468 f.deviceHandler.deviceType,
1469 onuDevice.Type,
1470 onuDevice.Id,
1471 onuDevice.ProxyAddress.DeviceId, "")
1472 if sendErr != nil {
1473 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1474 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1475 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1476 return sendErr
1477 }
1478 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05301479 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301480}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001481
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301482//UpdateOnuInfo function adds onu info to cache and kvstore
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001483func (f *OpenOltFlowMgr) UpdateOnuInfo(intfID uint32, onuID uint32, serialNum string) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301484
1485 f.lockCache.Lock()
1486 defer f.lockCache.Unlock()
1487 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
1488 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
1489 if err := f.resourceMgr.AddOnuInfo(intfID, onu); err != nil {
1490 log.Errorw("failed to add onu info", log.Fields{"onu": onu})
1491 return
1492 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001493 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
1494}
1495
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301496//addGemPortToOnuInfoMap function adds GEMport to ONU map
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001497func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(intfID uint32, onuID uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301498 f.lockCache.Lock()
1499 defer f.lockCache.Unlock()
1500 onugem := f.onuGemInfo[intfID]
1501 // update the gem to the local cache as well as to kv strore
1502 for idx, onu := range onugem {
1503 if onu.OnuID == onuID {
1504 // check if gem already exists , else update the cache and kvstore
1505 for _, gem := range onu.GemPorts {
1506 if gem == gemPort {
1507 log.Debugw("Gem already in cache, no need to update cache and kv store",
1508 log.Fields{"gem": gemPort})
1509 return
1510 }
1511 }
1512 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
1513 f.onuGemInfo[intfID] = onugem
1514 }
1515 }
1516 err := f.resourceMgr.AddGemToOnuGemInfo(intfID, onuID, gemPort)
1517 if err != nil {
1518 log.Errorw("Failed to add gem to onu", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001519 return
1520 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001521}
1522
1523// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001524
1525//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
1526func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301527
1528 f.lockCache.Lock()
1529 defer f.lockCache.Unlock()
1530
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001531 log.Debugw("Getting ONU ID from GEM port and PON port", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPortId": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301532 // get onuid from the onugem info cache
1533 onugem := f.onuGemInfo[intfID]
1534 for _, onu := range onugem {
1535 for _, gem := range onu.GemPorts {
1536 if gem == gemPortID {
1537 return onu.OnuID, nil
1538 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001539 }
1540 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001541 log.Errorw("onuid is not found", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPort": gemPortID})
1542 return uint32(0), errors.New("key error, onuid is not found") // ONU ID 0 is not a valid one
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001543}
1544
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001545//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
1546func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001547 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001548 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001549 var err error
1550
1551 if packetIn.IntfType == "pon" {
1552 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001553 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001554 log.Errorw("Unable to get ONU ID from GEM/PON port", log.Fields{"pon port": packetIn.IntfId, "gemport": packetIn.GemportId})
1555 return logicalPortNum, err
1556 }
1557 if packetIn.PortNo != 0 {
1558 logicalPortNum = packetIn.PortNo
1559 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001560 uniID := uint32(0) // FIXME - multi-uni support
1561 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001562 }
1563 // Store the gem port through which the packet_in came. Use the same gem port for packet_out
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301564 f.UpdateGemPortForPktIn(packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001565 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001566 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001567 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001568 log.Debugw("Retrieved logicalport from packet-in", log.Fields{
1569 "logicalPortNum": logicalPortNum,
1570 "IntfType": packetIn.IntfType,
1571 "packet": hex.EncodeToString(packetIn.Pkt),
1572 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001573 return logicalPortNum, nil
1574}
1575
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001576//GetPacketOutGemPortID returns gemPortId
1577func (f *OpenOltFlowMgr) GetPacketOutGemPortID(intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
1578 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001579 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301580
1581 f.lockCache.Lock()
1582 defer f.lockCache.Unlock()
1583 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum}
1584
1585 gemPortID, ok := f.packetInGemPort[pktInkey]
1586 if ok {
1587 log.Debugw("Found gemport for pktin key", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1588 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001589 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301590 //If gem is not found in cache try to get it from kv store, if found in kv store, update the cache and return.
1591 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(intfID, onuID, portNum)
1592 if err == nil {
1593 if gemPortID != 0 {
1594 f.packetInGemPort[pktInkey] = gemPortID
1595 log.Debugw("Found gem port from kv store and updating cache with gemport",
1596 log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1597 return gemPortID, nil
1598 }
1599 }
1600 log.Errorw("Failed to get gemport", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1601 return uint32(0), err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001602}
1603
Manikkaraj kb1d51442019-07-23 10:41:02 -04001604func installFlowOnAllGemports(
1605 f1 func(intfId uint32, onuId uint32, uniId uint32,
1606 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
1607 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32),
1608 f2 func(intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301609 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
1610 classifier map[string]interface{}, action map[string]interface{}),
Manikkaraj kb1d51442019-07-23 10:41:02 -04001611 args map[string]uint32,
1612 classifier map[string]interface{}, action map[string]interface{},
1613 logicalFlow *ofp.OfpFlowStats,
1614 gemPorts []uint32,
1615 FlowType string,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001616 vlanID ...uint32) {
1617 log.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
1618 for _, gemPortID := range gemPorts {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001619 if FlowType == HsiaFlow || FlowType == DhcpFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001620 f1(args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001621 } else if FlowType == EapolFlow {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301622 f2(args["intfId"], args["onuId"], args["uniId"], args["portNo"], logicalFlow, args["allocId"], gemPortID, vlanID[0], classifier, action)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001623 } else {
1624 log.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
1625 return
1626 }
1627 }
1628}
1629
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001630func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
1631 log.Debug("Adding trap-dhcp-of-nni-flow")
1632 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001633 classifier[PacketTagType] = DoubleTag
1634 action[TrapToHost] = true
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301635 var err error
1636 var networkInterfaceID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001637 /* We manage flowId resource pool on per PON port basis.
1638 Since this situation is tricky, as a hack, we pass the NNI port
1639 index (network_intf_id) as PON port Index for the flowId resource
1640 pool. Also, there is no ONU Id available for trapping DHCP packets
1641 on NNI port, use onu_id as -1 (invalid)
1642 ****************** CAVEAT *******************
1643 This logic works if the NNI Port Id falls within the same valid
1644 range of PON Port Ids. If this doesn't work for some OLT Vendor
1645 we need to have a re-look at this.
1646 *********************************************
1647 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001648 onuID := -1
1649 uniID := -1
1650 gemPortID := -1
1651 allocID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301652 networkInterfaceID, err = getNniIntfID(classifier, action)
1653 if err != nil {
1654 log.Error("Failed to get nniIntf ID")
1655 return
1656 }
1657
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001658 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301659 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001660 log.Debug("Flow-exists--not-re-adding")
1661 return
1662 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301663 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001664 if err != nil {
1665 log.Errorw("Flow id unavailable for DHCP traponNNI flow", log.Fields{"error": err})
1666 return
1667 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001668 var classifierProto *openoltpb2.Classifier
1669 var actionProto *openoltpb2.Action
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001670 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
1671 log.Error("Error in making classifier protobuf for dhcp trap on nni flow")
1672 return
1673 }
1674 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1675 if actionProto = makeOpenOltActionField(action); actionProto == nil {
1676 log.Error("Error in making action protobuf for dhcp trap on nni flow")
1677 return
1678 }
1679 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001680 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1681 OnuId: int32(onuID), // OnuId not required
1682 UniId: int32(uniID), // UniId not used
1683 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001684 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001685 AllocId: int32(allocID), // AllocId not used
1686 NetworkIntfId: int32(networkInterfaceID),
1687 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001688 Classifier: classifierProto,
1689 Action: actionProto,
1690 Priority: int32(logicalFlow.Priority),
1691 Cookie: logicalFlow.Cookie,
1692 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001693 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001694 log.Debug("DHCP trap on NNI flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301695 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001696 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1697 int32(onuID),
1698 int32(uniID),
1699 flowID, flowsToKVStore); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001700 log.Errorw("Error uploading DHCP DL flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1701 }
1702 }
1703 return
1704}
salmansiddiqui7ac62132019-08-22 03:58:50 +00001705
1706func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
1707 if MeterID == 0 { // This should never happen
1708 log.Error("Invalid meter id")
1709 return "", errors.New("invalid meter id")
1710 }
1711 if Dir == tp_pb.Direction_UPSTREAM {
1712 return "upstream", nil
1713 } else if Dir == tp_pb.Direction_DOWNSTREAM {
1714 return "downstream", nil
1715 }
1716 return "", nil
1717}
1718
1719func (f *OpenOltFlowMgr) checkAndAddFlow(args map[string]uint32, classifierInfo map[string]interface{},
Gamze Abakafee36392019-10-03 11:17:24 +00001720 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst *tp.TechProfile, gemPorts []uint32,
1721 TpID uint32, uni string) {
1722 var gemPort uint32
1723 intfID := args[IntfID]
1724 onuID := args[OnuID]
1725 uniID := args[UniID]
1726 portNo := args[PortNo]
1727 allocID := TpInst.UsScheduler.AllocID
salmansiddiqui7ac62132019-08-22 03:58:50 +00001728 if ipProto, ok := classifierInfo[IPProto]; ok {
1729 if ipProto.(uint32) == IPProtoDhcp {
1730 log.Info("Adding DHCP flow")
1731 if pcp, ok := classifierInfo[VlanPcp]; ok {
1732 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1733 tp_pb.Direction_UPSTREAM,
1734 pcp.(uint32))
1735 //Adding DHCP upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001736 f.addDHCPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001737 } else {
1738 //Adding DHCP upstream flow to all gemports
1739 installFlowOnAllGemports(f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, DhcpFlow)
1740 }
1741
1742 } else if ipProto == IgmpProto {
1743 log.Info("igmp flow add ignored, not implemented yet")
1744 return
1745 } else {
1746 log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
1747 return
1748 }
1749 } else if ethType, ok := classifierInfo[EthType]; ok {
1750 if ethType.(uint32) == EapEthType {
1751 log.Info("Adding EAPOL flow")
1752 var vlanID uint32
1753 if val, ok := classifierInfo[VlanVid]; ok {
1754 vlanID = (val.(uint32)) & VlanvIDMask
1755 } else {
1756 vlanID = DefaultMgmtVlan
1757 }
1758 if pcp, ok := classifierInfo[VlanPcp]; ok {
1759 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1760 tp_pb.Direction_UPSTREAM,
1761 pcp.(uint32))
1762
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301763 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID, gemPort, vlanID, classifierInfo, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001764 } else {
1765 installFlowOnAllGemports(nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, EapolFlow, vlanID)
1766 }
1767 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001768 } else if _, ok := actionInfo[PushVlan]; ok {
1769 log.Info("Adding upstream data rule")
1770 if pcp, ok := classifierInfo[VlanPcp]; ok {
1771 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1772 tp_pb.Direction_UPSTREAM,
1773 pcp.(uint32))
1774 //Adding HSIA upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001775 f.addUpstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001776 } else {
1777 //Adding HSIA upstream flow to all gemports
1778 installFlowOnAllGemports(f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1779 }
1780 } else if _, ok := actionInfo[PopVlan]; ok {
1781 log.Info("Adding Downstream data rule")
1782 if pcp, ok := classifierInfo[VlanPcp]; ok {
1783 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05001784 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001785 pcp.(uint32))
1786 //Adding HSIA downstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001787 f.addDownstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001788 } else {
1789 //Adding HSIA downstream flow to all gemports
1790 installFlowOnAllGemports(f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1791 }
1792 } else {
1793 log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
1794 return
1795 }
1796 // Send Techprofile download event to child device in go routine as it takes time
1797 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, TpID)
1798}
1799
Gamze Abakafee36392019-10-03 11:17:24 +00001800func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
1801 flowIDList := f.flowsUsedByGemPort[gemPK]
1802 if len(flowIDList) > 1 {
1803 return true
1804 }
1805 return false
1806}
1807
Girish Gowdra54934262019-11-13 14:19:55 +05301808func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
Gamze Abakafee36392019-10-03 11:17:24 +00001809 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ponIntf, onuID, uniID)
1810 tpGemPorts := tpInst.UpstreamGemPortAttributeList
1811 for _, currentGemPort := range currentGemPorts {
1812 for _, tpGemPort := range tpGemPorts {
1813 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
1814 return true, currentGemPort
1815 }
1816 }
1817 }
Girish Gowdra54934262019-11-13 14:19:55 +05301818 if tpInst.InstanceCtrl.Onu == "single-instance" {
1819 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
1820 f.resourceMgr.RemoveTechProfileIDForOnu(ponIntf, uint32(onuID), uint32(uniID), tpID)
1821 f.DeleteTechProfileInstance(ponIntf, uint32(onuID), uint32(uniID), "", tpID)
1822
1823 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
1824 // still be used on other uni ports.
1825 // So, we need to check and make sure that no other gem port is referring to the given TP ID
1826 // on any other uni port.
1827 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(tpID, ponIntf, onuID)
1828 for i := 0; i < len(tpInstances); i++ {
1829 tpI := tpInstances[i]
1830 tpGemPorts := tpI.UpstreamGemPortAttributeList
1831 for _, currentGemPort := range currentGemPorts {
1832 for _, tpGemPort := range tpGemPorts {
1833 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
1834 log.Debugw("tech-profile-is-in-use-by-gem", log.Fields{"gemPort": currentGemPort})
1835 return true, currentGemPort
1836 }
1837 }
1838 }
1839 }
1840 }
1841 log.Debug("tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00001842 return false, 0
1843}
1844
salmansiddiqui7ac62132019-08-22 03:58:50 +00001845func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07001846 for _, field := range flows.GetOfbFields(flow) {
1847 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001848 classifierInfo[EthType] = field.GetEthType()
1849 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001850 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001851 classifierInfo[IPProto] = field.GetIpProto()
1852 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001853 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001854 classifierInfo[InPort] = field.GetPort()
1855 log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001856 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05301857 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
salmansiddiqui7ac62132019-08-22 03:58:50 +00001858 log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001859 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001860 classifierInfo[VlanPcp] = field.GetVlanPcp()
1861 log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001862 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001863 classifierInfo[UDPDst] = field.GetUdpDst()
1864 log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001865 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001866 classifierInfo[UDPSrc] = field.GetUdpSrc()
1867 log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001868 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001869 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
1870 log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001871 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001872 classifierInfo[Ipv4Src] = field.GetIpv4Src()
1873 log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001874 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001875 classifierInfo[Metadata] = field.GetTableMetadata()
1876 log.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07001877 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001878 classifierInfo[TunnelID] = field.GetTunnelId()
1879 log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
1880 } else {
1881 log.Errorw("Un supported field type", log.Fields{"type": field.Type})
1882 return
1883 }
1884 }
1885}
1886
1887func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07001888 for _, action := range flows.GetActions(flow) {
1889 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001890 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001891 actionInfo[Output] = out.GetPort()
1892 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001893 } else {
1894 log.Error("Invalid output port in action")
1895 return errors.New("invalid output port in action")
1896 }
Scott Baker355d1742019-10-24 10:57:52 -07001897 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001898 actionInfo[PopVlan] = true
1899 log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001900 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001901 if out := action.GetPush(); out != nil {
1902 if tpid := out.GetEthertype(); tpid != 0x8100 {
1903 log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
1904 } else {
1905 actionInfo[PushVlan] = true
1906 actionInfo[TPID] = tpid
1907 log.Debugw("action-type-push-vlan",
1908 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
1909 }
1910 }
Scott Baker355d1742019-10-24 10:57:52 -07001911 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001912 if out := action.GetSetField(); out != nil {
1913 if field := out.GetField(); field != nil {
1914 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
1915 log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
1916 return errors.New("invalid openflow class")
1917 }
1918 /*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
1919 if ofbField := field.GetOfbField(); ofbField != nil {
1920 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
1921 if vlan := ofbField.GetVlanVid(); vlan != 0 {
1922 actionInfo[VlanVid] = vlan & 0xfff
1923 log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
1924 } else {
1925 log.Error("No Invalid vlan id in set vlan-vid action")
1926 }
1927 } else {
1928 log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
1929 }
1930 }
1931 }
1932 }
1933 } else {
1934 log.Errorw("Un supported action type", log.Fields{"type": action.Type})
1935 return errors.New("un supported action type")
1936 }
1937 }
1938 return nil
1939}
1940
1941func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001942 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001943 log.Debug("Controller bound trap flows, getting inport from tunnelid")
1944 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
1945 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001946 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001947 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07001948 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 +00001949 } else {
1950 log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1951 return errors.New("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1952 }
1953 }
1954 } else {
1955 log.Debug("Non-Controller flows, getting uniport from tunnelid")
1956 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07001957 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001958 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001959 actionInfo[Output] = uniPort
1960 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 +00001961 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001962 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 +00001963 return errors.New("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid")
1964 }
1965 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
1966 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001967 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001968 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07001969 log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[Output].(uint32),
1970 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001971 } else {
1972 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 -07001973 "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001974 return errors.New("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid")
1975 }
1976 }
1977 }
1978 return nil
1979}
Gamze Abakafee36392019-10-03 11:17:24 +00001980
Chaitrashree G S90a17952019-11-14 21:51:21 -05001981func getTpIDFromFlow(flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00001982 /* Metadata 8 bytes:
1983 Most Significant 2 Bytes = Inner VLAN
1984 Next 2 Bytes = Tech Profile ID(TPID)
1985 Least Significant 4 Bytes = Port ID
1986 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
1987 subscriber related flows.
1988 */
1989 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
1990 if metadata == 0 {
Chaitrashree G S90a17952019-11-14 21:51:21 -05001991 log.Error("metadata-is-not-present-in-flow-which-is-mandatory")
1992 return 0, errors.New("metadata-is-not-present-in-flow-which-is-mandatory")
Gamze Abakafee36392019-10-03 11:17:24 +00001993 }
1994 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001995 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00001996}
1997
1998func appendUnique(slice []uint32, item uint32) []uint32 {
1999 for _, sliceElement := range slice {
2000 if sliceElement == item {
2001 return slice
2002 }
2003 }
2004 return append(slice, item)
2005}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302006
2007// getNniIntfID gets nni intf id from the flow classifier/action
2008func getNniIntfID(classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
2009
2010 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
2011 if portType == voltha.Port_PON_OLT {
2012 intfID := IntfIDFromNniPortNum(action[Output].(uint32))
2013 log.Debugw("output Nni IntfID is", log.Fields{"intfid": intfID})
2014 return intfID, nil
2015 } else if portType == voltha.Port_ETHERNET_NNI {
2016 intfID := IntfIDFromNniPortNum(classifier[InPort].(uint32))
2017 log.Debugw("input Nni IntfID is", log.Fields{"intfid": intfID})
2018 return intfID, nil
2019 }
2020 return uint32(0), nil
2021}
2022
2023// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
2024func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32) {
2025 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort}
2026
2027 f.lockCache.Lock()
2028 defer f.lockCache.Unlock()
2029 _, ok := f.packetInGemPort[pktInkey]
2030 if ok {
2031 log.Debugw("pktin key found in cache , no need to update kv as we are assuming both will be in sync",
2032 log.Fields{"pktinkey": pktInkey, "gem": gemPort})
2033 } else {
2034 f.packetInGemPort[pktInkey] = gemPort
2035
2036 f.resourceMgr.UpdateGemPortForPktIn(pktInkey, gemPort)
2037 log.Debugw("pktin key not found in local cache updating cache and kv store", log.Fields{"pktinkey": pktInkey, "gem": gemPort})
2038 }
2039 return
2040}
2041
2042// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
2043func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(intfID uint32, onuID uint32, portNum uint32) {
2044
2045 f.lockCache.Lock()
2046 defer f.lockCache.Unlock()
2047 onugem := f.onuGemInfo[intfID]
2048 for idx, onu := range onugem {
2049 if onu.OnuID == onuID {
2050 for _, uni := range onu.UniPorts {
2051 if uni == portNum {
2052 log.Debugw("uni already in cache, no need to update cache and kv store",
2053 log.Fields{"uni": portNum})
2054 return
2055 }
2056 }
2057 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
2058 f.onuGemInfo[intfID] = onugem
2059 }
2060 }
2061 f.resourceMgr.AddUniPortToOnuInfo(intfID, onuID, portNum)
2062}