blob: 565c8c86eb552bbde7fe5f8e62500dda8f72eb5a [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 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530203 //Load flowID list per gem map per interface from the kvstore.
204 flowMgr.loadFlowIDlistForGem(idx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530205 }
206 flowMgr.lockCache = sync.RWMutex{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530207 log.Info("Initialization of flow manager success!!")
208 return &flowMgr
209}
210
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700211func (f *OpenOltFlowMgr) generateStoredFlowID(flowID uint32, direction string) (uint64, error) {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700212 if direction == Upstream {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400213 log.Debug("upstream flow, shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700214 return 0x1<<15 | uint64(flowID), nil
David K. Bainbridge82efc492019-09-04 09:57:11 -0700215 } else if direction == Downstream {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400216 log.Debug("downstream flow, not shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700217 return uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400218 } else {
219 log.Debug("Unrecognized direction")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700220 return 0, fmt.Errorf("unrecognized direction %s", direction)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400221 }
222}
223
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700224func (f *OpenOltFlowMgr) registerFlow(flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400225 log.Debug("Registering Flow for Device ", log.Fields{"flow": flowFromCore},
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700226 log.Fields{"device": f.deviceHandler.deviceID})
Gamze Abakafee36392019-10-03 11:17:24 +0000227 gemPK := gemPortKey{uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId)}
228 flowIDList, ok := f.flowsUsedByGemPort[gemPK]
229 if !ok {
230 flowIDList = []uint32{deviceFlow.FlowId}
231 }
232 flowIDList = appendUnique(flowIDList, deviceFlow.FlowId)
233 f.flowsUsedByGemPort[gemPK] = flowIDList
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530234 // update the flowids for a gem to the KVstore
235 f.resourceMgr.UpdateFlowIDsForGem(uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400236}
237
salmansiddiqui7ac62132019-08-22 03:58:50 +0000238func (f *OpenOltFlowMgr) divideAndAddFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32,
239 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
240 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) {
Gamze Abakafee36392019-10-03 11:17:24 +0000241 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530242 var gemPorts []uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400243 var TpInst *tp.TechProfile
manikkaraj kbf256be2019-03-25 00:13:48 +0530244
Manikkaraj kb1d51442019-07-23 10:41:02 -0400245 log.Infow("Dividing flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "portNo": portNo,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000246 "classifier": classifierInfo, "action": actionInfo, "UsMeterID": UsMeterID, "DsMeterID": DsMeterID, "TpID": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400247 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
248 // is because the flow is an NNI flow and there would be no onu resources associated with it
249 // TODO: properly deal with NNI flows
Manikkaraj kb1d51442019-07-23 10:41:02 -0400250 if onuID <= 0 {
Matt Jeanneret77199612019-07-26 18:08:35 -0400251 log.Errorw("No onu id for flow", log.Fields{"portNo": portNo, "classifer": classifierInfo, "action": actionInfo})
manikkaraj kbf256be2019-03-25 00:13:48 +0530252 return
253 }
254
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530255 uni := getUniPortPath(intfID, int32(onuID), int32(uniID))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400256 log.Debugw("Uni port name", log.Fields{"uni": uni})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000257 allocID, gemPorts, TpInst = f.createTcontGemports(intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
Gamze Abakafee36392019-10-03 11:17:24 +0000258 if allocID == 0 || gemPorts == nil || TpInst == nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400259 log.Error("alloc-id-gem-ports-tp-unavailable")
260 return
261 }
262
263 /* Flows can be added specific to gemport if p-bits are received.
264 * If no pbit mentioned then adding flows for all gemports
manikkaraj kbf256be2019-03-25 00:13:48 +0530265 */
Manikkaraj kb1d51442019-07-23 10:41:02 -0400266
267 args := make(map[string]uint32)
Gamze Abakafee36392019-10-03 11:17:24 +0000268 args[IntfID] = intfID
269 args[OnuID] = onuID
270 args[UniID] = uniID
271 args[PortNo] = portNo
272 args[AllocID] = allocID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400273
Gamze Abakafee36392019-10-03 11:17:24 +0000274 f.checkAndAddFlow(args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530275}
276
salmansiddiqui7ac62132019-08-22 03:58:50 +0000277// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
Gamze Abakafee36392019-10-03 11:17:24 +0000278func (f *OpenOltFlowMgr) CreateSchedulerQueues(sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400279
Gamze Abakafee36392019-10-03 11:17:24 +0000280 log.Debugw("CreateSchedulerQueues", log.Fields{"Dir": sq.direction, "IntfID": sq.intfID,
281 "OnuID": sq.onuID, "UniID": sq.uniID, "TpID": sq.tpID, "MeterID": sq.meterID,
282 "TpInst": sq.tpInst, "flowMetadata": sq.flowMetadata})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400283
Gamze Abakafee36392019-10-03 11:17:24 +0000284 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000285 if err != nil {
286 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400287 }
288
289 /* Lets make a simple assumption that if the meter-id is present on the KV store,
290 * then the scheduler and queues configuration is applied on the OLT device
291 * in the given direction.
292 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000293
Manikkaraj kb1d51442019-07-23 10:41:02 -0400294 var SchedCfg *tp_pb.SchedulerConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000295 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400296 if err != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000297 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 -0400298 return err
299 }
300 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000301 if KvStoreMeter.MeterId == sq.meterID {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400302 log.Debug("Scheduler already created for upstream")
303 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400304 }
Gamze Abakafee36392019-10-03 11:17:24 +0000305 log.Errorw("Dynamic meter update not supported", log.Fields{"KvStoreMeterId": KvStoreMeter.MeterId, "MeterID-in-flow": sq.meterID})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000306 return errors.New("invalid-meter-id-in-flow")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400307 }
Gamze Abakafee36392019-10-03 11:17:24 +0000308 log.Debugw("Meter-does-not-exist-Creating-new", log.Fields{"MeterID": sq.meterID, "Direction": Direction})
309 if sq.direction == tp_pb.Direction_UPSTREAM {
310 SchedCfg = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
311 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
312 SchedCfg = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400313 }
314 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000315 if sq.flowMetadata != nil {
316 for _, meter := range sq.flowMetadata.Meters {
317 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400318 meterConfig = meter
319 log.Debugw("Found-meter-config-from-flowmetadata", log.Fields{"meterConfig": meterConfig})
320 break
321 }
322 }
323 } else {
324 log.Error("Flow-metadata-is-not-present-in-flow")
325 }
326 if meterConfig == nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000327 log.Errorw("Could-not-get-meterbands-from-flowMetadata", log.Fields{"flowMetadata": sq.flowMetadata,
328 "MeterID": sq.meterID})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000329 return errors.New("failed-to-get-meter-from-flowMetadata")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400330 } else if len(meterConfig.Bands) < MaxMeterBand {
Gamze Abakafee36392019-10-03 11:17:24 +0000331 log.Errorw("Invalid-number-of-bands-in-meter", log.Fields{"Bands": meterConfig.Bands, "MeterID": sq.meterID})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000332 return errors.New("invalid-number-of-bands-in-meter")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400333 }
334 cir := meterConfig.Bands[0].Rate
335 cbs := meterConfig.Bands[0].BurstSize
336 eir := meterConfig.Bands[1].Rate
337 ebs := meterConfig.Bands[1].BurstSize
338 pir := cir + eir
339 pbs := cbs + ebs
340 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
341
Gamze Abakafee36392019-10-03 11:17:24 +0000342 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Manikkaraj kb1d51442019-07-23 10:41:02 -0400343
344 log.Debugw("Sending Traffic scheduler create to device", log.Fields{"Direction": Direction, "TrafficScheds": TrafficSched})
345 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000346 IntfId: sq.intfID, OnuId: sq.onuID,
347 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400348 TrafficScheds: TrafficSched}); err != nil {
349 log.Errorw("Failed to create traffic schedulers", log.Fields{"error": err})
350 return err
351 }
352 // On receiving the CreateTrafficQueues request, the driver should create corresponding
353 // downstream queues.
Gamze Abakafee36392019-10-03 11:17:24 +0000354 trafficQueues := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400355 log.Debugw("Sending Traffic Queues create to device", log.Fields{"Direction": Direction, "TrafficQueues": trafficQueues})
356 if _, err := f.deviceHandler.Client.CreateTrafficQueues(context.Background(),
Gamze Abakafee36392019-10-03 11:17:24 +0000357 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
358 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400359 TrafficQueues: trafficQueues}); err != nil {
360 log.Errorw("Failed to create traffic queues in device", log.Fields{"error": err})
361 return err
362 }
363
salmansiddiqui7ac62132019-08-22 03:58:50 +0000364 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400365 * store the meter id on the KV store, for further reference.
366 */
Gamze Abakafee36392019-10-03 11:17:24 +0000367 if err := f.resourceMgr.UpdateMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterConfig); err != nil {
368 log.Error("Failed to update meter id for onu %d, meterid %d", sq.onuID, sq.meterID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400369 return err
370 }
371 log.Debugw("updated-meter-info into KV store successfully", log.Fields{"Direction": Direction,
372 "Meter": meterConfig})
373 return nil
374}
375
salmansiddiqui7ac62132019-08-22 03:58:50 +0000376// 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 +0000377func (f *OpenOltFlowMgr) RemoveSchedulerQueues(sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400378
379 var Direction string
380 var SchedCfg *tp_pb.SchedulerConfig
381 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000382 log.Debugw("Removing schedulers and Queues in OLT", log.Fields{"Direction": sq.direction, "IntfID": sq.intfID,
383 "OnuID": sq.onuID, "UniID": sq.uniID, "UniPort": sq.uniPort})
384 if sq.direction == tp_pb.Direction_UPSTREAM {
385 SchedCfg = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400386 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000387 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
388 SchedCfg = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400389 Direction = "downstream"
390 }
391
Gamze Abakafee36392019-10-03 11:17:24 +0000392 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400393 if err != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000394 log.Errorf("Failed to get Meter for Onu %d", sq.onuID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400395 return err
396 }
397 if KVStoreMeter == nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000398 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 -0400399 return nil
400 }
401 cir := KVStoreMeter.Bands[0].Rate
402 cbs := KVStoreMeter.Bands[0].BurstSize
403 eir := KVStoreMeter.Bands[1].Rate
404 ebs := KVStoreMeter.Bands[1].BurstSize
405 pir := cir + eir
406 pbs := cbs + ebs
407
408 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
409
Gamze Abakafee36392019-10-03 11:17:24 +0000410 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
411 TrafficQueues := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400412
413 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(context.Background(),
Gamze Abakafee36392019-10-03 11:17:24 +0000414 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
415 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400416 TrafficQueues: TrafficQueues}); err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000417 log.Errorw("Failed to remove traffic queues", log.Fields{"error": err})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400418 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400419 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000420 log.Debug("Removed traffic queues successfully")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400421 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000422 IntfId: sq.intfID, OnuId: sq.onuID,
423 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400424 TrafficScheds: TrafficSched}); err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000425 log.Errorw("failed to remove traffic schedulers", log.Fields{"error": err})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400426 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400427 }
428
salmansiddiqui7ac62132019-08-22 03:58:50 +0000429 log.Debug("Removed traffic schedulers successfully")
430
431 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400432 * delete the meter id on the KV store.
433 */
Gamze Abakafee36392019-10-03 11:17:24 +0000434 err = f.resourceMgr.RemoveMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400435 if err != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000436 log.Errorf("Failed to remove meter for onu %d, meter id %d", sq.onuID, KVStoreMeter.MeterId)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000437 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400438 }
439 log.Debugw("Removed-meter-from-KV-store successfully", log.Fields{"MeterId": KVStoreMeter.MeterId, "dir": Direction})
440 return err
441}
442
Gamze Abakafee36392019-10-03 11:17:24 +0000443// This function allocates tconts and GEM ports for an ONU
444func (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) {
445 var allocIDs []uint32
446 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530447 var gemPortIDs []uint32
Gamze Abakafee36392019-10-03 11:17:24 +0000448
449 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(intfID, onuID, uniID)
450 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400451
452 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530453
454 log.Infow("creating-new-tcont-and-gem", log.Fields{"pon": intfID, "onu": onuID, "uni": uniID})
455
Manikkaraj kb1d51442019-07-23 10:41:02 -0400456 // Check tech profile instance already exists for derived port name
Girish Gowdra54934262019-11-13 14:19:55 +0530457 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000458 if techProfileInstance == nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530459 log.Infow("tp-instance-not-found--creating-new", log.Fields{"path": tpPath})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000460 techProfileInstance = f.techprofile[intfID].CreateTechProfInstance(TpID, uni, intfID)
461 if techProfileInstance == nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530462 // This should not happen, something wrong in KV backend transaction
463 log.Error("tp-instance-create-failed")
Gamze Abakafee36392019-10-03 11:17:24 +0000464 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530465 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000466 f.resourceMgr.UpdateTechProfileIDForOnu(intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530467 } else {
468 log.Debugw("Tech-profile-instance-already-exist-for-given port-name", log.Fields{"uni": uni})
469 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400470 if UsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000471 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
472 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
473 if err := f.CreateSchedulerQueues(sq); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400474 log.Errorw("CreateSchedulerQueues Failed-upstream", log.Fields{"error": err, "meterID": UsMeterID})
Gamze Abakafee36392019-10-03 11:17:24 +0000475 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400476 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530477 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400478 if DsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000479 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
480 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
481 if err := f.CreateSchedulerQueues(sq); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400482 log.Errorw("CreateSchedulerQueues Failed-downstream", log.Fields{"error": err, "meterID": DsMeterID})
Gamze Abakafee36392019-10-03 11:17:24 +0000483 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400484 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530485 }
Gamze Abakafee36392019-10-03 11:17:24 +0000486
487 allocID := techProfileInstance.UsScheduler.AllocID
488 allocIDs = appendUnique(allocIDs, allocID)
489
490 for _, gem := range techProfileInstance.UpstreamGemPortAttributeList {
491 allgemPortIDs = appendUnique(allgemPortIDs, gem.GemportID)
492 gemPortIDs = append(gemPortIDs, gem.GemportID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400493 }
Gamze Abakafee36392019-10-03 11:17:24 +0000494
495 log.Debugw("Allocated Tcont and GEM ports", log.Fields{"allocIDs": allocIDs, "gemports": allgemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530496 // Send Tconts and GEM ports to KV store
Gamze Abakafee36392019-10-03 11:17:24 +0000497 f.storeTcontsGEMPortsIntoKVStore(intfID, onuID, uniID, allocIDs, allgemPortIDs)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000498 return allocID, gemPortIDs, techProfileInstance
manikkaraj kbf256be2019-03-25 00:13:48 +0530499}
500
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700501func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530502
503 log.Debugw("Storing allocated Tconts and GEM ports into KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700504 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "allocID": allocID, "gemPortIDs": gemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530505 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700506 if err := f.resourceMgr.UpdateAllocIdsForOnu(intfID, onuID, uniID, allocID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530507 log.Error("Errow while uploading allocID to KV store")
508 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700509 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(intfID, onuID, uniID, gemPortIDs); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530510 log.Error("Errow while uploading GEMports to KV store")
511 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700512 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(gemPortIDs, intfID, onuID, uniID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530513 log.Error("Errow while uploading gemtopon map to KV store")
514 }
515 log.Debug("Stored tconts and GEM into KV store successfully")
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400516 for _, gemPort := range gemPortIDs {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700517 f.addGemPortToOnuInfoMap(intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400518 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530519}
520
521func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000522 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530523 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000524 for _, intfID := range techRange.IntfIds {
525 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400526 tpCount++
salmansiddiqui7ac62132019-08-22 03:58:50 +0000527 log.Debugw("Init tech profile done", log.Fields{"intfID": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530528 }
529 }
530 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400531 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530532 log.Errorw("Error while populating techprofile",
Manikkaraj kb1d51442019-07-23 10:41:02 -0400533 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000534 return errors.New("error while populating techprofile mgrs")
manikkaraj kbf256be2019-03-25 00:13:48 +0530535 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400536 log.Infow("Populated techprofile for ponports successfully",
537 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
manikkaraj kbf256be2019-03-25 00:13:48 +0530538 return nil
539}
540
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700541func (f *OpenOltFlowMgr) addUpstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530542 portNo uint32, uplinkClassifier map[string]interface{},
543 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700544 allocID uint32, gemportID uint32) {
545 uplinkClassifier[PacketTagType] = SingleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530546 log.Debugw("Adding upstream data flow", log.Fields{"uplinkClassifier": uplinkClassifier, "uplinkAction": uplinkAction})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700547 f.addHSIAFlow(intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700548 Upstream, logicalFlow, allocID, gemportID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530549 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530550}
551
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700552func (f *OpenOltFlowMgr) addDownstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530553 portNo uint32, downlinkClassifier map[string]interface{},
554 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700555 allocID uint32, gemportID uint32) {
556 downlinkClassifier[PacketTagType] = DoubleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530557 log.Debugw("Adding downstream data flow", log.Fields{"downlinkClassifier": downlinkClassifier,
558 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400559 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
560 if vlan, exists := downlinkClassifier[VlanVid]; exists {
561 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700562 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Manikkaraj kb1d51442019-07-23 10:41:02 -0400563 if uint32(metadata.(uint64)) == MkUniPortNum(intfID, onuID, uniID) {
564 log.Infow("Ignoring DL trap device flow from core", log.Fields{"flow": logicalFlow})
565 return
566 }
567 }
568 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530569 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400570
Manikkaraj k884c1242019-04-11 16:26:42 +0530571 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700572 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400573 // vlan_vid is a uint32. must be type asserted as such or conversion fails
574 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530575 if ok {
576 downlinkAction[VlanVid] = dlClVid & 0xfff
577 } else {
578 log.Error("dl-classifier-vid-type-conversion-failed")
579 return
580 }
581
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700582 f.addHSIAFlow(intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700583 Downstream, logicalFlow, allocID, gemportID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530584}
585
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700586func (f *OpenOltFlowMgr) addHSIAFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +0530587 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700588 allocID uint32, gemPortID uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530589 var networkIntfID uint32
Manikkaraj k884c1242019-04-11 16:26:42 +0530590 /* One of the OLT platform (Broadcom BAL) requires that symmetric
591 flows require the same flow_id to be used across UL and DL.
592 Since HSIA flow is the only symmetric flow currently, we need to
593 re-use the flow_id across both direction. The 'flow_category'
594 takes priority over flow_cookie to find any available HSIA_FLOW
595 id for the ONU.
596 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700597 log.Debugw("Adding HSIA flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "classifier": classifier,
598 "action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530599 "logicalFlow": *logicalFlow})
Gamze Abakafee36392019-10-03 11:17:24 +0000600 var vlanPbit uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400601 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000602 vlanPbit = classifier[VlanPcp].(uint32)
603 log.Debugw("Found pbit in the flow", log.Fields{"VlanPbit": vlanPbit})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400604 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700605 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530606 flowID, err := f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530607 if err != nil {
608 log.Errorw("Flow id unavailable for HSIA flow", log.Fields{"direction": direction})
609 return
610 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700611 var classifierProto *openoltpb2.Classifier
612 var actionProto *openoltpb2.Action
Manikkaraj k884c1242019-04-11 16:26:42 +0530613 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
614 log.Error("Error in making classifier protobuf for hsia flow")
615 return
616 }
617 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
618 if actionProto = makeOpenOltActionField(action); actionProto == nil {
619 log.Errorw("Error in making action protobuf for hsia flow", log.Fields{"direction": direction})
620 return
621 }
622 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530623 networkIntfID, err = getNniIntfID(classifier, action)
624 if err != nil {
625 log.Error("Failed to get nniIntf ID")
626 return
627 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700628 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
629 OnuId: int32(onuID),
630 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000631 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530632 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700633 AllocId: int32(allocID),
634 NetworkIntfId: int32(networkIntfID),
635 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530636 Classifier: classifierProto,
637 Action: actionProto,
638 Priority: int32(logicalFlow.Priority),
639 Cookie: logicalFlow.Cookie,
640 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400641 if ok := f.addFlowToDevice(logicalFlow, &flow); ok {
Manikkaraj k884c1242019-04-11 16:26:42 +0530642 log.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530643 flowsToKVStore := f.getUpdatedFlowInfo(&flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
Manikkaraj k884c1242019-04-11 16:26:42 +0530644 if err := f.updateFlowInfoToKVStore(flow.AccessIntfId,
645 flow.OnuId,
646 flow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400647 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530648 log.Errorw("Error uploading HSIA flow into KV store", log.Fields{"flow": flow, "direction": direction, "error": err})
649 return
650 }
651 }
652}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700653func (f *OpenOltFlowMgr) addDHCPTrapFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32) {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530654
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700655 var dhcpFlow openoltpb2.Flow
656 var actionProto *openoltpb2.Action
657 var classifierProto *openoltpb2.Classifier
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530658 var flowID uint32
659 networkIntfID, err := getNniIntfID(classifier, action)
660 if err != nil {
661 log.Error("Failed to get nniIntf ID")
662 return
663 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530664
665 // Clear the action map
666 for k := range action {
667 delete(action, k)
668 }
669
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700670 action[TrapToHost] = true
671 classifier[UDPSrc] = uint32(68)
672 classifier[UDPDst] = uint32(67)
673 classifier[PacketTagType] = SingleTag
674 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530675
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700676 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530677
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530678 flowID, err = f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0 /*classifier[VLAN_PCP].(uint32)*/)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530679
680 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700681 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530682 return
683 }
684
685 log.Debugw("Creating UL DHCP flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID})
686
687 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
688 log.Error("Error in making classifier protobuf for ul flow")
689 return
690 }
691 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
692 if actionProto = makeOpenOltActionField(action); actionProto == nil {
693 log.Error("Error in making action protobuf for ul flow")
694 return
695 }
696
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700697 dhcpFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
698 OnuId: int32(onuID),
699 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530700 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700701 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700702 AllocId: int32(allocID),
703 NetworkIntfId: int32(networkIntfID),
704 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530705 Classifier: classifierProto,
706 Action: actionProto,
707 Priority: int32(logicalFlow.Priority),
708 Cookie: logicalFlow.Cookie,
709 PortNo: portNo}
710
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400711 if ok := f.addFlowToDevice(logicalFlow, &dhcpFlow); ok {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530712 log.Debug("DHCP UL flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530713 flowsToKVStore := f.getUpdatedFlowInfo(&dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530714 if err := f.updateFlowInfoToKVStore(dhcpFlow.AccessIntfId,
715 dhcpFlow.OnuId,
716 dhcpFlow.UniId,
717 dhcpFlow.FlowId, flowsToKVStore); err != nil {
718 log.Errorw("Error uploading DHCP UL flow into KV store", log.Fields{"flow": dhcpFlow, "error": err})
719 return
720 }
721 }
722
manikkaraj kbf256be2019-03-25 00:13:48 +0530723 return
724}
725
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700726// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530727func (f *OpenOltFlowMgr) addEAPOLFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, vlanID uint32, classifier map[string]interface{}, action map[string]interface{}) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700728 log.Debugw("Adding EAPOL to device", log.Fields{"intfId": intfID, "onuId": onuID, "portNo": portNo, "allocId": allocID, "gemPortId": gemPortID, "vlanId": vlanID, "flow": logicalFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +0530729
730 uplinkClassifier := make(map[string]interface{})
731 uplinkAction := make(map[string]interface{})
732 downlinkClassifier := make(map[string]interface{})
733 downlinkAction := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700734 var upstreamFlow openoltpb2.Flow
735 var downstreamFlow openoltpb2.Flow
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530736 var networkIntfID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530737
738 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700739 uplinkClassifier[EthType] = uint32(EapEthType)
740 uplinkClassifier[PacketTagType] = SingleTag
741 uplinkClassifier[VlanVid] = vlanID
manikkaraj kbf256be2019-03-25 00:13:48 +0530742 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700743 uplinkAction[TrapToHost] = true
744 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530745 //Add Uplink EAPOL Flow
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530746 uplinkFlowID, err := f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530747 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700748 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manikkaraj k884c1242019-04-11 16:26:42 +0530749 return
manikkaraj kbf256be2019-03-25 00:13:48 +0530750 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700751 var classifierProto *openoltpb2.Classifier
752 var actionProto *openoltpb2.Action
753 log.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530754
755 if classifierProto = makeOpenOltClassifierField(uplinkClassifier); classifierProto == nil {
756 log.Error("Error in making classifier protobuf for ul flow")
757 return
758 }
759 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
760 if actionProto = makeOpenOltActionField(uplinkAction); actionProto == nil {
761 log.Error("Error in making action protobuf for ul flow")
762 return
763 }
764 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530765 networkIntfID, err = getNniIntfID(classifier, action)
766 if err != nil {
767 log.Error("Failed to get nniIntf ID")
768 return
769 }
770
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700771 upstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
772 OnuId: int32(onuID),
773 UniId: int32(uniID),
774 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700775 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700776 AllocId: int32(allocID),
777 NetworkIntfId: int32(networkIntfID),
778 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530779 Classifier: classifierProto,
780 Action: actionProto,
781 Priority: int32(logicalFlow.Priority),
782 Cookie: logicalFlow.Cookie,
783 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400784 if ok := f.addFlowToDevice(logicalFlow, &upstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530785 log.Debug("EAPOL UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400786 flowCategory := "EAPOL"
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530787 flowsToKVStore := f.getUpdatedFlowInfo(&upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
manikkaraj kbf256be2019-03-25 00:13:48 +0530788 if err := f.updateFlowInfoToKVStore(upstreamFlow.AccessIntfId,
789 upstreamFlow.OnuId,
790 upstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400791 upstreamFlow.FlowId,
792 /* lowCategory, */
793 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530794 log.Errorw("Error uploading EAPOL UL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
795 return
796 }
797 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400798 // Dummy Downstream flow due to BAL 2.6 limitation
799 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530800 /* Add Downstream EAPOL Flow, Only for first EAP flow (BAL
801 # requirement)
802 # On one of the platforms (Broadcom BAL), when same DL classifier
803 # vlan was used across multiple ONUs, eapol flow re-adds after
804 # flow delete (cases of onu reboot/disable) fails.
805 # In order to generate unique vlan, a combination of intf_id
806 # onu_id and uniId is used.
807 # uniId defaults to 0, so add 1 to it.
808 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700809 log.Debugw("Creating DL EAPOL flow with default vlan", log.Fields{"vlan": vlanID})
810 specialVlanDlFlow := 4090 - intfID*onuID*(uniID+1)
manikkaraj kbf256be2019-03-25 00:13:48 +0530811 // Assert that we do not generate invalid vlans under no condition
812 if specialVlanDlFlow <= 2 {
813 log.Fatalw("invalid-vlan-generated", log.Fields{"vlan": specialVlanDlFlow})
814 return
815 }
816 log.Debugw("specialVlanEAPOLDlFlow:", log.Fields{"dl_vlan": specialVlanDlFlow})
817 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700818 downlinkClassifier[PacketTagType] = SingleTag
Manikkaraj kb1d51442019-07-23 10:41:02 -0400819 downlinkClassifier[EthType] = uint32(EapEthType)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700820 downlinkClassifier[VlanVid] = uint32(specialVlanDlFlow)
manikkaraj kbf256be2019-03-25 00:13:48 +0530821 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700822 downlinkAction[PushVlan] = true
823 downlinkAction[VlanVid] = vlanID
824 flowStoreCookie := getFlowStoreCookie(downlinkClassifier, gemPortID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530825 downlinkFlowID, err := f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530826 if err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530827 log.Errorw("flowId unavailable for DL EAPOL",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700828 log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
manikkaraj kbf256be2019-03-25 00:13:48 +0530829 return
830 }
831 log.Debugw("Creating DL EAPOL flow",
salmansiddiqui7ac62132019-08-22 03:58:50 +0000832 log.Fields{"dl_classifier": downlinkClassifier, "dl_action": downlinkAction, "downlinkFlowID": downlinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530833 if classifierProto = makeOpenOltClassifierField(downlinkClassifier); classifierProto == nil {
834 log.Error("Error in making classifier protobuf for downlink flow")
835 return
836 }
837 if actionProto = makeOpenOltActionField(downlinkAction); actionProto == nil {
838 log.Error("Error in making action protobuf for dl flow")
839 return
840 }
841 // Downstream flow in grpc protobuf
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700842 downstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
843 OnuId: int32(onuID),
844 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000845 FlowId: downlinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700846 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700847 AllocId: int32(allocID),
848 NetworkIntfId: int32(networkIntfID),
849 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530850 Classifier: classifierProto,
851 Action: actionProto,
852 Priority: int32(logicalFlow.Priority),
853 Cookie: logicalFlow.Cookie,
854 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400855 if ok := f.addFlowToDevice(logicalFlow, &downstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530856 log.Debug("EAPOL DL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400857 flowCategory := ""
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530858 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamFlow, flowStoreCookie, flowCategory, downlinkFlowID, logicalFlow.Id)
manikkaraj kbf256be2019-03-25 00:13:48 +0530859 if err := f.updateFlowInfoToKVStore(downstreamFlow.AccessIntfId,
860 downstreamFlow.OnuId,
861 downstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400862 downstreamFlow.FlowId,
863 /* flowCategory, */
864 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530865 log.Errorw("Error uploading EAPOL DL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
866 return
867 }
868 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530869 }
870 log.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
871}
872
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700873func makeOpenOltClassifierField(classifierInfo map[string]interface{}) *openoltpb2.Classifier {
874 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -0700875
876 classifier.EthType, _ = classifierInfo[EthType].(uint32)
877 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
878 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
879 vid := vlanID & VlanvIDMask
880 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -0400881 classifier.OVid = vid
882 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530883 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700884 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
885 vid := uint32(metadata)
886 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -0400887 classifier.IVid = vid
888 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530889 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700890 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400891 if vlanPcp == 0 {
892 classifier.OPbits = VlanPCPMask
893 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700894 classifier.OPbits = vlanPcp & VlanPCPMask
Manikkaraj kb1d51442019-07-23 10:41:02 -0400895 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530896 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700897 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
898 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
899 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
900 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
901 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
902 classifier.PktTagType = pktTagType
903
904 switch pktTagType {
905 case SingleTag:
906 case DoubleTag:
907 case Untagged:
908 default:
manikkaraj kbf256be2019-03-25 00:13:48 +0530909 log.Error("Invalid tag type in classifier") // should not hit
910 return nil
911 }
912 }
913 return &classifier
914}
915
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700916func makeOpenOltActionField(actionInfo map[string]interface{}) *openoltpb2.Action {
917 var actionCmd openoltpb2.ActionCmd
918 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +0530919 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700920 if _, ok := actionInfo[PopVlan]; ok {
921 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530922 action.Cmd.RemoveOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700923 } else if _, ok := actionInfo[PushVlan]; ok {
924 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +0530925 action.Cmd.AddOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700926 } else if _, ok := actionInfo[TrapToHost]; ok {
927 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +0530928 } else {
929 log.Errorw("Invalid-action-field", log.Fields{"action": actionInfo})
930 return nil
931 }
932 return &action
933}
934
Manikkaraj kb1d51442019-07-23 10:41:02 -0400935func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uni string, TpID uint32) string {
936 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530937}
938
Gamze Abakafee36392019-10-03 11:17:24 +0000939// DeleteTechProfileInstances removes the tech profile instances from persistent storage
940func (f *OpenOltFlowMgr) DeleteTechProfileInstances(intfID uint32, onuID uint32, uniID uint32, sn string) error {
941 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(intfID, onuID, uniID)
Devmalya Paul495b94a2019-08-27 19:42:00 -0400942 uniPortName := fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +0000943 for _, tpID := range tpIDList {
944 if err := f.DeleteTechProfileInstance(intfID, onuID, uniID, uniPortName, tpID); err != nil {
945 log.Debugw("Failed-to-delete-tp-instance-from-kv-store", log.Fields{"tp-id": tpID, "uni-port-name": uniPortName})
Girish Gowdra54934262019-11-13 14:19:55 +0530946 // return err
947 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +0000948 }
949 }
950 return nil
951}
952
953// DeleteTechProfileInstance removes the tech profile instance from persistent storage
954func (f *OpenOltFlowMgr) DeleteTechProfileInstance(intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
955 if uniPortName == "" {
956 uniPortName = fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
957 }
Devmalya Paul495b94a2019-08-27 19:42:00 -0400958 if err := f.techprofile[intfID].DeleteTechProfileInstance(tpID, uniPortName); err != nil {
959 log.Debugw("Failed-to-delete-tp-instance-from-kv-store", log.Fields{"tp-id": tpID, "uni-port-name": uniPortName})
960 return err
961 }
962 return nil
963}
964
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700965func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +0530966 if len(classifier) == 0 { // should never happen
967 log.Error("Invalid classfier object")
968 return 0
969 }
970 var jsonData []byte
971 var flowString string
972 var err error
973 // TODO: Do we need to marshall ??
974 if jsonData, err = json.Marshal(classifier); err != nil {
975 log.Error("Failed to encode classifier")
976 return 0
977 }
978 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700979 if gemPortID != 0 {
980 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +0530981 }
982 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700983 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +0530984 hash := big.NewInt(0)
985 hash.SetBytes(h.Sum(nil))
986 return hash.Uint64()
987}
988
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530989func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openoltpb2.Flow, flowStoreCookie uint64, flowCategory string, deviceFlowID uint32, logicalFlowID uint64) *[]rsrcMgr.FlowInfo {
990 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700991 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400992 /* For flows which trap out of the NNI, the AccessIntfId is invalid
993 (set to -1). In such cases, we need to refer to the NetworkIntfId .
994 */
995 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700996 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400997 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700998 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400999 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001000 // Get existing flows matching flowid for given subscriber from KV store
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301001 existingFlows := f.resourceMgr.GetFlowIDInfo(intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001002 if existingFlows != nil {
1003 log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001004 //for _, f := range *existingFlows {
1005 // flows = append(flows, f)
1006 //}
1007 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001008 }
1009 log.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
manikkaraj kbf256be2019-03-25 00:13:48 +05301010 return &flows
1011}
1012
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001013//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
1014// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
1015// var intfId uint32
1016// /* For flows which trap out of the NNI, the AccessIntfId is invalid
1017// (set to -1). In such cases, we need to refer to the NetworkIntfId .
1018// */
1019// if flow.AccessIntfId != -1 {
1020// intfId = uint32(flow.AccessIntfId)
1021// } else {
1022// intfId = uint32(flow.NetworkIntfId)
1023// }
1024// // Get existing flows matching flowid for given subscriber from KV store
1025// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
1026// if existingFlows != nil {
1027// log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
1028// for _, f := range *existingFlows {
1029// flows = append(flows, f)
1030// }
1031// }
1032// log.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
1033// return &flows
1034//}
1035
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001036func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
manikkaraj k17652a72019-05-06 09:06:36 -04001037 log.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001038 if err := f.resourceMgr.UpdateFlowIDInfo(intfID, onuID, uniID, flowID, flows); err != nil {
manikkaraj k17652a72019-05-06 09:06:36 -04001039 log.Debug("Error while Storing flow into KV store")
1040 return err
1041 }
1042 log.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +05301043 return nil
1044}
1045
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001046func (f *OpenOltFlowMgr) addFlowToDevice(logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) bool {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001047
1048 var intfID uint32
1049 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1050 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1051 */
1052 if deviceFlow.AccessIntfId != -1 {
1053 intfID = uint32(deviceFlow.AccessIntfId)
1054 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001055 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001056 intfID = uint32(deviceFlow.NetworkIntfId)
1057 }
1058
manikkaraj kbf256be2019-03-25 00:13:48 +05301059 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1060 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001061
1062 st, _ := status.FromError(err)
1063 if st.Code() == codes.AlreadyExists {
Gamze Abakafee36392019-10-03 11:17:24 +00001064 log.Debug("Flow already exists", log.Fields{"err": err, "deviceFlow": deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301065 return false
1066 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001067
1068 if err != nil {
1069 log.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": deviceFlow})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001070 f.resourceMgr.FreeFlowID(intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001071 return false
1072 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001073 f.registerFlow(logicalFlow, deviceFlow)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301074 log.Debugw("Flow added to device successfully ", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001075 return true
1076}
1077
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001078func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) bool {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001079 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1080 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1081 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001082 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
1083 log.Warnw("Can not remove flow from device since it's unreachable", log.Fields{"err": err, "deviceFlow": deviceFlow})
1084 //Assume the flow is removed
1085 return true
1086 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001087 log.Errorw("Failed to Remove flow from device", log.Fields{"err": err, "deviceFlow": deviceFlow})
1088 return false
serkant.uluderya245caba2019-09-24 23:15:29 -07001089
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001090 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001091 log.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301092 return true
1093}
1094
1095/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1096 //update core flows_proxy : flows_proxy.update('/', flows)
1097}
1098
1099func generateStoredId(flowId uint32, direction string)uint32{
1100
David K. Bainbridge82efc492019-09-04 09:57:11 -07001101 if direction == Upstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301102 log.Debug("Upstream flow shifting flowid")
1103 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001104 }else if direction == Downstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301105 log.Debug("Downstream flow not shifting flowid")
1106 return flowId
1107 }else{
1108 log.Errorw("Unrecognized direction",log.Fields{"direction": direction})
1109 return flowId
1110 }
1111}
1112
1113*/
1114
Humera Kouser94d7a842019-08-25 19:04:32 -04001115func (f *OpenOltFlowMgr) addLLDPFlow(flow *ofp.OfpFlowStats, portNo uint32) {
1116
1117 classifierInfo := make(map[string]interface{})
1118 actionInfo := make(map[string]interface{})
1119
1120 classifierInfo[EthType] = uint32(LldpEthType)
1121 classifierInfo[PacketTagType] = Untagged
1122 actionInfo[TrapToHost] = true
1123
1124 // LLDP flow is installed to trap LLDP packets on the NNI port.
1125 // We manage flow_id resource pool on per PON port basis.
1126 // Since this situation is tricky, as a hack, we pass the NNI port
1127 // index (network_intf_id) as PON port Index for the flow_id resource
1128 // pool. Also, there is no ONU Id available for trapping LLDP packets
1129 // on NNI port, use onu_id as -1 (invalid)
1130 // ****************** CAVEAT *******************
1131 // This logic works if the NNI Port Id falls within the same valid
1132 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1133 // we need to have a re-look at this.
1134 // *********************************************
1135
1136 var onuID = -1
1137 var uniID = -1
1138 var gemPortID = -1
1139
1140 var networkInterfaceID = IntfIDFromNniPortNum(portNo)
1141 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301142 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Humera Kouser94d7a842019-08-25 19:04:32 -04001143 log.Debug("Flow-exists--not-re-adding")
1144 return
1145 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301146 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001147
1148 if err != nil {
1149 log.Errorw("Flow id unavailable for LLDP traponNNI flow", log.Fields{"error": err})
1150 return
1151 }
1152 var classifierProto *openoltpb2.Classifier
1153 var actionProto *openoltpb2.Action
1154 if classifierProto = makeOpenOltClassifierField(classifierInfo); classifierProto == nil {
1155 log.Error("Error in making classifier protobuf for LLDP trap on nni flow")
1156 return
1157 }
1158 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1159 if actionProto = makeOpenOltActionField(actionInfo); actionProto == nil {
1160 log.Error("Error in making action protobuf for LLDP trap on nni flow")
1161 return
1162 }
1163 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
1164
1165 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1166 OnuId: int32(onuID), // OnuId not required
1167 UniId: int32(uniID), // UniId not used
1168 FlowId: flowID,
1169 FlowType: Downstream,
1170 NetworkIntfId: int32(networkInterfaceID),
1171 GemportId: int32(gemPortID),
1172 Classifier: classifierProto,
1173 Action: actionProto,
1174 Priority: int32(flow.Priority),
1175 Cookie: flow.Cookie,
1176 PortNo: portNo}
1177 if ok := f.addFlowToDevice(flow, &downstreamflow); ok {
1178 log.Debug("LLDP trap on NNI flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301179 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID, flow.Id)
Humera Kouser94d7a842019-08-25 19:04:32 -04001180 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1181 int32(onuID),
1182 int32(uniID),
1183 flowID, flowsToKVStore); err != nil {
1184 log.Errorw("Error uploading LLDP flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1185 }
1186 }
1187 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301188}
1189
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301190func getUniPortPath(intfID uint32, onuID int32, uniID int32) string {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001191 return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1192}
1193
1194//getOnuChildDevice to fetch onu
1195func (f *OpenOltFlowMgr) getOnuChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
1196 log.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
1197 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
1198 onuDevice := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301199 if onuDevice == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001200 log.Errorw("onu not found", log.Fields{"intfId": parentPortNo, "onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301201 return nil, errors.New("onu not found")
manikkaraj kbf256be2019-03-25 00:13:48 +05301202 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301203 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1204 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301205}
1206
1207func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001208 log.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301209 return nil
1210}
1211
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001212func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
1213 log.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301214}
1215
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001216func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001217 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001218 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001219 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001220 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001221}
1222
Girish Gowdra6b130582019-11-20 16:45:20 +05301223func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1224 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
1225 if err != nil {
1226 log.Errorw("error fetching child device from core", log.Fields{"onuId": onuID})
1227 return err
1228 }
1229
1230 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
1231 log.Debugw("sending gem port delete to openonu adapter", log.Fields{"msg": *delGemPortMsg})
1232 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1233 delGemPortMsg,
1234 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
1235 f.deviceHandler.deviceType,
1236 onuDevice.Type,
1237 onuDevice.Id,
1238 onuDevice.ProxyAddress.DeviceId, ""); sendErr != nil {
1239 log.Errorw("failure sending del gem port to onu adapter", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1240 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1241 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1242 return sendErr
1243 }
1244 log.Debugw("success sending del gem port to onu adapter", log.Fields{"msg": delGemPortMsg})
1245 return nil
1246}
1247
1248func (f *OpenOltFlowMgr) sendDeleteTcontToChild(intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1249 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
1250 if err != nil {
1251 log.Errorw("error fetching child device from core", log.Fields{"onuId": onuID})
1252 return err
1253 }
1254
1255 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
1256 log.Debugw("sending tcont delete to openonu adapter", log.Fields{"msg": *delTcontMsg})
1257 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1258 delTcontMsg,
1259 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
1260 f.deviceHandler.deviceType,
1261 onuDevice.Type,
1262 onuDevice.Id,
1263 onuDevice.ProxyAddress.DeviceId, ""); sendErr != nil {
1264 log.Errorw("failure sending del tcont to onu adapter", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1265 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1266 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1267 return sendErr
1268 }
1269 log.Debugw("success sending del tcont to onu adapter", log.Fields{"msg": delTcontMsg})
1270 return nil
1271}
1272
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301273//clearResources clears pon resources in kv store and the device
1274func (f *OpenOltFlowMgr) clearResources(flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
1275 gemPortID int32, flowID uint32, flowDirection string,
1276 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001277
Chaitrashree G S90a17952019-11-14 21:51:21 -05001278 tpID, err := getTpIDFromFlow(flow)
1279 if err != nil {
1280 log.Error("metadata-is-not-present-invalid-flow-to-process", log.Fields{"pon": Intf, "onuID": onuID, "uniID": uniID})
1281 return err
1282 }
Gamze Abakafee36392019-10-03 11:17:24 +00001283
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001284 if len(updatedFlows) >= 0 {
1285 // There are still flows referencing the same flow_id.
1286 // So the flow should not be freed yet.
1287 // For ex: Case of HSIA where same flow is shared
1288 // between DS and US.
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301289 f.updateFlowInfoToKVStore(int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001290 if len(updatedFlows) == 0 {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301291 log.Debugw("Releasing flow Id to resource manager", log.Fields{"Intf": Intf, "onuId": onuID, "uniId": uniID, "flowId": flowID})
1292 f.resourceMgr.FreeFlowID(Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001293
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301294 uni := getUniPortPath(Intf, onuID, uniID)
1295 tpPath := f.getTPpath(Intf, uni, tpID)
Gamze Abakafee36392019-10-03 11:17:24 +00001296 log.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301297 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(tpID, tpPath)
Gamze Abakafee36392019-10-03 11:17:24 +00001298 if err != nil { // This should not happen, something wrong in KV backend transaction
1299 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": 20, "path": tpPath})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301300 return err
Gamze Abakafee36392019-10-03 11:17:24 +00001301 }
1302 if techprofileInst == nil {
1303 log.Errorw("Tech-profile-instance-does-not-exist-in-KV Store", log.Fields{"tpPath": tpPath})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301304 return err
Gamze Abakafee36392019-10-03 11:17:24 +00001305 }
1306
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301307 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00001308 if f.isGemPortUsedByAnotherFlow(gemPK) {
1309 flowIDs := f.flowsUsedByGemPort[gemPK]
1310 for i, flowIDinMap := range flowIDs {
1311 if flowIDinMap == flowID {
1312 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301313 // everytime flowsUsedByGemPort cache is updated the same should be updated
1314 // in kv store by calling UpdateFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001315 f.flowsUsedByGemPort[gemPK] = flowIDs
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301316 f.resourceMgr.UpdateFlowIDsForGem(Intf, uint32(gemPortID), flowIDs)
Gamze Abakafee36392019-10-03 11:17:24 +00001317 break
1318 }
1319 }
1320 log.Debugw("Gem port id is still used by other flows", log.Fields{"gemPortID": gemPortID, "usedByFlows": flowIDs})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301321 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00001322 }
Gamze Abakafee36392019-10-03 11:17:24 +00001323 log.Debugf("Gem port id %d is not used by another flow - releasing the gem port", gemPortID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301324 f.resourceMgr.RemoveGemPortIDForOnu(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001325 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1326 // 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 +05301327 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(uint32(gemPortID), Intf)
Gamze Abakafee36392019-10-03 11:17:24 +00001328 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301329 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1330 // by calling DeleteFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001331 delete(f.flowsUsedByGemPort, gemPK)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301332 f.resourceMgr.DeleteFlowIDsForGem(Intf, uint32(gemPortID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301333 f.resourceMgr.FreeGemPortID(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001334 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05301335 // Delete the gem port on the ONU.
1336 if err := f.sendDeleteGemPortToChild(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
1337 log.Errorw("error processing delete gem-port towards onu",
1338 log.Fields{"err": err, "pon": Intf, "onuID": onuID, "uniID": uniID, "gemPortId": gemPortID})
1339 }
Gamze Abakafee36392019-10-03 11:17:24 +00001340
Girish Gowdra54934262019-11-13 14:19:55 +05301341 ok, _ := f.isTechProfileUsedByAnotherGem(Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001342 if !ok {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301343 f.resourceMgr.RemoveTechProfileIDForOnu(Intf, uint32(onuID), uint32(uniID), tpID)
1344 f.RemoveSchedulerQueues(schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1345 f.RemoveSchedulerQueues(schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1346 f.DeleteTechProfileInstance(Intf, uint32(onuID), uint32(uniID), "", tpID)
1347 f.resourceMgr.FreeAllocID(Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301348 // Delete the TCONT on the ONU.
1349 if err := f.sendDeleteTcontToChild(Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
1350 log.Errorw("error processing delete tcont towards onu",
1351 log.Fields{"pon": Intf, "onuID": onuID, "uniID": uniID, "allocId": techprofileInst.UsScheduler.AllocID})
1352 }
Gamze Abakafee36392019-10-03 11:17:24 +00001353 }
1354 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001355 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301356 return nil
1357}
1358
1359func (f *OpenOltFlowMgr) clearFlowFromResourceManager(flow *ofp.OfpFlowStats, flowDirection string) {
1360
1361 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowDirection": flowDirection, "flow": *flow})
1362 var updatedFlows []rsrcMgr.FlowInfo
1363 var flowID uint32
1364 var onuID, uniID int32
1365 classifierInfo := make(map[string]interface{})
1366
1367 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
1368 if err != nil {
1369 log.Error(err)
1370 return
1371 }
1372 onuID = int32(onu)
1373 uniID = int32(uni)
1374
1375 for _, field := range flows.GetOfbFields(flow) {
1376 if field.Type == flows.IP_PROTO {
1377 classifierInfo[IPProto] = field.GetIpProto()
1378 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
1379 }
1380 }
1381 log.Debugw("Extracted access info from flow to be deleted",
1382 log.Fields{"ponIntf": Intf, "onuID": onuID, "uniID": uniID})
1383
1384 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1385 onuID = -1
1386 uniID = -1
1387 log.Debug("Trap on nni flow set oni, uni to -1")
1388 Intf = IntfIDFromNniPortNum(inPort)
1389 }
1390 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(Intf, onuID, uniID)
1391 for _, flowID = range flowIds {
1392 flowInfo := f.resourceMgr.GetFlowIDInfo(Intf, onuID, uniID, flowID)
1393 if flowInfo == nil {
1394 log.Debugw("No FlowInfo found found in KV store",
1395 log.Fields{"Intf": Intf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1396 return
1397 }
1398 updatedFlows = nil
1399 for _, flow := range *flowInfo {
1400 updatedFlows = append(updatedFlows, flow)
1401 }
1402
1403 for i, storedFlow := range updatedFlows {
1404 if flow.Id == storedFlow.LogicalFlowID {
1405 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
1406 log.Debugw("Flow to be deleted", log.Fields{"flow": storedFlow})
1407 if ok := f.removeFlowFromDevice(&removeFlowMessage); ok {
1408 log.Debug("Flow removed from device successfully")
1409 //Remove the Flow from FlowInfo
1410 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1411 err = f.clearResources(flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
1412 flowID, flowDirection, portNum, updatedFlows)
1413 if err != nil {
1414 log.Error("Failed to clear resources for flow", log.Fields{"flow": storedFlow})
1415 return
1416 }
1417 } else {
1418 log.Error("Failed to remove flow from device")
1419 return
1420 }
1421 }
1422 }
1423 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001424}
1425
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001426//RemoveFlow removes the flow from the device
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001427func (f *OpenOltFlowMgr) RemoveFlow(flow *ofp.OfpFlowStats) {
1428 log.Debugw("Removing Flow", log.Fields{"flow": flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301429 var direction string
1430 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001431
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301432 for _, action := range flows.GetActions(flow) {
1433 if action.Type == flows.OUTPUT {
1434 if out := action.GetOutput(); out != nil {
1435 actionInfo[Output] = out.GetPort()
1436 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
1437 } else {
1438 log.Error("Invalid output port in action")
1439 return
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001440 }
1441 }
1442 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301443 if IsUpstream(actionInfo[Output].(uint32)) {
1444 direction = Upstream
1445 } else {
1446 direction = Downstream
1447 }
1448
1449 f.clearFlowFromResourceManager(flow, direction) //TODO: Take care of the limitations
1450
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001451 return
1452}
1453
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001454// AddFlow add flow to device
Manikkaraj kb1d51442019-07-23 10:41:02 -04001455func (f *OpenOltFlowMgr) AddFlow(flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001456 classifierInfo := make(map[string]interface{})
1457 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001458 var UsMeterID uint32
1459 var DsMeterID uint32
1460
1461 log.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001462 formulateClassifierInfoFromFlow(classifierInfo, flow)
1463
1464 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
1465 if err != nil {
1466 // Error logging is already done in the called function
1467 // So just return in case of error
1468 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301469 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001470
manikkaraj k17652a72019-05-06 09:06:36 -04001471 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00001472 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
1473 if err != nil {
1474 // error if any, already logged in the called function
1475 return
manikkaraj k17652a72019-05-06 09:06:36 -04001476 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001477
David K. Bainbridge82efc492019-09-04 09:57:11 -07001478 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[Output]})
1479 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00001480
Humera Kouser94d7a842019-08-25 19:04:32 -04001481 if ethType, ok := classifierInfo[EthType]; ok {
1482 if ethType.(uint32) == LldpEthType {
1483 log.Info("Adding LLDP flow")
1484 f.addLLDPFlow(flow, portNo)
1485 return
1486 }
1487 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001488 if ipProto, ok := classifierInfo[IPProto]; ok {
1489 if ipProto.(uint32) == IPProtoDhcp {
1490 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001491 if udpSrc.(uint32) == uint32(67) {
1492 log.Debug("trap-dhcp-from-nni-flow")
1493 f.addDHCPTrapFlowOnNNI(flow, classifierInfo, portNo)
1494 return
1495 }
1496 }
1497 }
1498 }
A R Karthick1f85b802019-10-11 05:06:05 +00001499
1500 f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301501 f.resourceMgr.AddUniPortToOnuInfo(intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00001502
Chaitrashree G S90a17952019-11-14 21:51:21 -05001503 TpID, err := getTpIDFromFlow(flow)
1504 if err != nil {
1505 log.Error("metadata-is-not-present-invalid-flow-to-process", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1506 return
1507 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001508 log.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001509 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07001510 UsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001511 log.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
1512 } else {
Scott Baker355d1742019-10-24 10:57:52 -07001513 DsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001514 log.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
1515
1516 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001517 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001518}
1519
1520//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04001521func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001522
1523 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301524 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001525 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301526 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301527 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301528 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04001529
Manikkaraj kb1d51442019-07-23 10:41:02 -04001530 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001531 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
manikkaraj k17652a72019-05-06 09:06:36 -04001532 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
1533 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1534 tpDownloadMsg,
1535 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
1536 f.deviceHandler.deviceType,
1537 onuDevice.Type,
1538 onuDevice.Id,
1539 onuDevice.ProxyAddress.DeviceId, "")
1540 if sendErr != nil {
1541 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1542 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1543 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1544 return sendErr
1545 }
1546 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05301547 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301548}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001549
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301550//UpdateOnuInfo function adds onu info to cache and kvstore
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001551func (f *OpenOltFlowMgr) UpdateOnuInfo(intfID uint32, onuID uint32, serialNum string) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301552
1553 f.lockCache.Lock()
1554 defer f.lockCache.Unlock()
1555 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
1556 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
1557 if err := f.resourceMgr.AddOnuInfo(intfID, onu); err != nil {
1558 log.Errorw("failed to add onu info", log.Fields{"onu": onu})
1559 return
1560 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001561 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
1562}
1563
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301564//addGemPortToOnuInfoMap function adds GEMport to ONU map
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001565func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(intfID uint32, onuID uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301566 f.lockCache.Lock()
1567 defer f.lockCache.Unlock()
1568 onugem := f.onuGemInfo[intfID]
1569 // update the gem to the local cache as well as to kv strore
1570 for idx, onu := range onugem {
1571 if onu.OnuID == onuID {
1572 // check if gem already exists , else update the cache and kvstore
1573 for _, gem := range onu.GemPorts {
1574 if gem == gemPort {
1575 log.Debugw("Gem already in cache, no need to update cache and kv store",
1576 log.Fields{"gem": gemPort})
1577 return
1578 }
1579 }
1580 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
1581 f.onuGemInfo[intfID] = onugem
1582 }
1583 }
1584 err := f.resourceMgr.AddGemToOnuGemInfo(intfID, onuID, gemPort)
1585 if err != nil {
1586 log.Errorw("Failed to add gem to onu", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001587 return
1588 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001589}
1590
1591// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001592
1593//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
1594func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301595
1596 f.lockCache.Lock()
1597 defer f.lockCache.Unlock()
1598
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001599 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 +05301600 // get onuid from the onugem info cache
1601 onugem := f.onuGemInfo[intfID]
1602 for _, onu := range onugem {
1603 for _, gem := range onu.GemPorts {
1604 if gem == gemPortID {
1605 return onu.OnuID, nil
1606 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001607 }
1608 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001609 log.Errorw("onuid is not found", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPort": gemPortID})
1610 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 -04001611}
1612
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001613//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
1614func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001615 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001616 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001617 var err error
1618
1619 if packetIn.IntfType == "pon" {
1620 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001621 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001622 log.Errorw("Unable to get ONU ID from GEM/PON port", log.Fields{"pon port": packetIn.IntfId, "gemport": packetIn.GemportId})
1623 return logicalPortNum, err
1624 }
1625 if packetIn.PortNo != 0 {
1626 logicalPortNum = packetIn.PortNo
1627 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001628 uniID := uint32(0) // FIXME - multi-uni support
1629 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001630 }
1631 // 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 +05301632 f.UpdateGemPortForPktIn(packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001633 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001634 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001635 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001636 log.Debugw("Retrieved logicalport from packet-in", log.Fields{
1637 "logicalPortNum": logicalPortNum,
1638 "IntfType": packetIn.IntfType,
1639 "packet": hex.EncodeToString(packetIn.Pkt),
1640 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001641 return logicalPortNum, nil
1642}
1643
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001644//GetPacketOutGemPortID returns gemPortId
1645func (f *OpenOltFlowMgr) GetPacketOutGemPortID(intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
1646 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001647 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301648
1649 f.lockCache.Lock()
1650 defer f.lockCache.Unlock()
1651 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum}
1652
1653 gemPortID, ok := f.packetInGemPort[pktInkey]
1654 if ok {
1655 log.Debugw("Found gemport for pktin key", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1656 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001657 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301658 //If gem is not found in cache try to get it from kv store, if found in kv store, update the cache and return.
1659 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(intfID, onuID, portNum)
1660 if err == nil {
1661 if gemPortID != 0 {
1662 f.packetInGemPort[pktInkey] = gemPortID
1663 log.Debugw("Found gem port from kv store and updating cache with gemport",
1664 log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1665 return gemPortID, nil
1666 }
1667 }
1668 log.Errorw("Failed to get gemport", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1669 return uint32(0), err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001670}
1671
Manikkaraj kb1d51442019-07-23 10:41:02 -04001672func installFlowOnAllGemports(
1673 f1 func(intfId uint32, onuId uint32, uniId uint32,
1674 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
1675 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32),
1676 f2 func(intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301677 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
1678 classifier map[string]interface{}, action map[string]interface{}),
Manikkaraj kb1d51442019-07-23 10:41:02 -04001679 args map[string]uint32,
1680 classifier map[string]interface{}, action map[string]interface{},
1681 logicalFlow *ofp.OfpFlowStats,
1682 gemPorts []uint32,
1683 FlowType string,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001684 vlanID ...uint32) {
1685 log.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
1686 for _, gemPortID := range gemPorts {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001687 if FlowType == HsiaFlow || FlowType == DhcpFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001688 f1(args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001689 } else if FlowType == EapolFlow {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301690 f2(args["intfId"], args["onuId"], args["uniId"], args["portNo"], logicalFlow, args["allocId"], gemPortID, vlanID[0], classifier, action)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001691 } else {
1692 log.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
1693 return
1694 }
1695 }
1696}
1697
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001698func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
1699 log.Debug("Adding trap-dhcp-of-nni-flow")
1700 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001701 classifier[PacketTagType] = DoubleTag
1702 action[TrapToHost] = true
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301703 var err error
1704 var networkInterfaceID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001705 /* We manage flowId resource pool on per PON port basis.
1706 Since this situation is tricky, as a hack, we pass the NNI port
1707 index (network_intf_id) as PON port Index for the flowId resource
1708 pool. Also, there is no ONU Id available for trapping DHCP packets
1709 on NNI port, use onu_id as -1 (invalid)
1710 ****************** CAVEAT *******************
1711 This logic works if the NNI Port Id falls within the same valid
1712 range of PON Port Ids. If this doesn't work for some OLT Vendor
1713 we need to have a re-look at this.
1714 *********************************************
1715 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001716 onuID := -1
1717 uniID := -1
1718 gemPortID := -1
1719 allocID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301720 networkInterfaceID, err = getNniIntfID(classifier, action)
1721 if err != nil {
1722 log.Error("Failed to get nniIntf ID")
1723 return
1724 }
1725
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001726 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301727 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001728 log.Debug("Flow-exists--not-re-adding")
1729 return
1730 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301731 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001732 if err != nil {
1733 log.Errorw("Flow id unavailable for DHCP traponNNI flow", log.Fields{"error": err})
1734 return
1735 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001736 var classifierProto *openoltpb2.Classifier
1737 var actionProto *openoltpb2.Action
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001738 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
1739 log.Error("Error in making classifier protobuf for dhcp trap on nni flow")
1740 return
1741 }
1742 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1743 if actionProto = makeOpenOltActionField(action); actionProto == nil {
1744 log.Error("Error in making action protobuf for dhcp trap on nni flow")
1745 return
1746 }
1747 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001748 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1749 OnuId: int32(onuID), // OnuId not required
1750 UniId: int32(uniID), // UniId not used
1751 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001752 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001753 AllocId: int32(allocID), // AllocId not used
1754 NetworkIntfId: int32(networkInterfaceID),
1755 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001756 Classifier: classifierProto,
1757 Action: actionProto,
1758 Priority: int32(logicalFlow.Priority),
1759 Cookie: logicalFlow.Cookie,
1760 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001761 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001762 log.Debug("DHCP trap on NNI flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301763 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001764 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1765 int32(onuID),
1766 int32(uniID),
1767 flowID, flowsToKVStore); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001768 log.Errorw("Error uploading DHCP DL flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1769 }
1770 }
1771 return
1772}
salmansiddiqui7ac62132019-08-22 03:58:50 +00001773
1774func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
1775 if MeterID == 0 { // This should never happen
1776 log.Error("Invalid meter id")
1777 return "", errors.New("invalid meter id")
1778 }
1779 if Dir == tp_pb.Direction_UPSTREAM {
1780 return "upstream", nil
1781 } else if Dir == tp_pb.Direction_DOWNSTREAM {
1782 return "downstream", nil
1783 }
1784 return "", nil
1785}
1786
1787func (f *OpenOltFlowMgr) checkAndAddFlow(args map[string]uint32, classifierInfo map[string]interface{},
Gamze Abakafee36392019-10-03 11:17:24 +00001788 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst *tp.TechProfile, gemPorts []uint32,
1789 TpID uint32, uni string) {
1790 var gemPort uint32
1791 intfID := args[IntfID]
1792 onuID := args[OnuID]
1793 uniID := args[UniID]
1794 portNo := args[PortNo]
1795 allocID := TpInst.UsScheduler.AllocID
salmansiddiqui7ac62132019-08-22 03:58:50 +00001796 if ipProto, ok := classifierInfo[IPProto]; ok {
1797 if ipProto.(uint32) == IPProtoDhcp {
1798 log.Info("Adding DHCP flow")
1799 if pcp, ok := classifierInfo[VlanPcp]; ok {
1800 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1801 tp_pb.Direction_UPSTREAM,
1802 pcp.(uint32))
1803 //Adding DHCP upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001804 f.addDHCPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001805 } else {
1806 //Adding DHCP upstream flow to all gemports
1807 installFlowOnAllGemports(f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, DhcpFlow)
1808 }
1809
1810 } else if ipProto == IgmpProto {
1811 log.Info("igmp flow add ignored, not implemented yet")
1812 return
1813 } else {
1814 log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
1815 return
1816 }
1817 } else if ethType, ok := classifierInfo[EthType]; ok {
1818 if ethType.(uint32) == EapEthType {
1819 log.Info("Adding EAPOL flow")
1820 var vlanID uint32
1821 if val, ok := classifierInfo[VlanVid]; ok {
1822 vlanID = (val.(uint32)) & VlanvIDMask
1823 } else {
1824 vlanID = DefaultMgmtVlan
1825 }
1826 if pcp, ok := classifierInfo[VlanPcp]; ok {
1827 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1828 tp_pb.Direction_UPSTREAM,
1829 pcp.(uint32))
1830
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301831 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID, gemPort, vlanID, classifierInfo, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001832 } else {
1833 installFlowOnAllGemports(nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, EapolFlow, vlanID)
1834 }
1835 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001836 } else if _, ok := actionInfo[PushVlan]; ok {
1837 log.Info("Adding upstream data rule")
1838 if pcp, ok := classifierInfo[VlanPcp]; ok {
1839 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1840 tp_pb.Direction_UPSTREAM,
1841 pcp.(uint32))
1842 //Adding HSIA upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001843 f.addUpstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001844 } else {
1845 //Adding HSIA upstream flow to all gemports
1846 installFlowOnAllGemports(f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1847 }
1848 } else if _, ok := actionInfo[PopVlan]; ok {
1849 log.Info("Adding Downstream data rule")
1850 if pcp, ok := classifierInfo[VlanPcp]; ok {
1851 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05001852 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001853 pcp.(uint32))
1854 //Adding HSIA downstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001855 f.addDownstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001856 } else {
1857 //Adding HSIA downstream flow to all gemports
1858 installFlowOnAllGemports(f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1859 }
1860 } else {
1861 log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
1862 return
1863 }
1864 // Send Techprofile download event to child device in go routine as it takes time
1865 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, TpID)
1866}
1867
Gamze Abakafee36392019-10-03 11:17:24 +00001868func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
1869 flowIDList := f.flowsUsedByGemPort[gemPK]
1870 if len(flowIDList) > 1 {
1871 return true
1872 }
1873 return false
1874}
1875
Girish Gowdra54934262019-11-13 14:19:55 +05301876func (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 +00001877 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ponIntf, onuID, uniID)
1878 tpGemPorts := tpInst.UpstreamGemPortAttributeList
1879 for _, currentGemPort := range currentGemPorts {
1880 for _, tpGemPort := range tpGemPorts {
1881 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
1882 return true, currentGemPort
1883 }
1884 }
1885 }
Girish Gowdra54934262019-11-13 14:19:55 +05301886 if tpInst.InstanceCtrl.Onu == "single-instance" {
1887 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
1888 f.resourceMgr.RemoveTechProfileIDForOnu(ponIntf, uint32(onuID), uint32(uniID), tpID)
1889 f.DeleteTechProfileInstance(ponIntf, uint32(onuID), uint32(uniID), "", tpID)
1890
1891 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
1892 // still be used on other uni ports.
1893 // So, we need to check and make sure that no other gem port is referring to the given TP ID
1894 // on any other uni port.
1895 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(tpID, ponIntf, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301896 log.Debugw("got single instance tp instances", log.Fields{"tpInstances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05301897 for i := 0; i < len(tpInstances); i++ {
1898 tpI := tpInstances[i]
1899 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05301900 for _, tpGemPort := range tpGemPorts {
1901 if tpGemPort.GemportID != gemPortID {
1902 log.Debugw("single instance tp is in use by gem", log.Fields{"gemPort": tpGemPort.GemportID})
1903 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05301904 }
1905 }
1906 }
1907 }
Girish Gowdra6b130582019-11-20 16:45:20 +05301908 log.Debug("tech profile is not in use by any gem")
Gamze Abakafee36392019-10-03 11:17:24 +00001909 return false, 0
1910}
1911
salmansiddiqui7ac62132019-08-22 03:58:50 +00001912func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07001913 for _, field := range flows.GetOfbFields(flow) {
1914 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001915 classifierInfo[EthType] = field.GetEthType()
1916 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001917 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001918 classifierInfo[IPProto] = field.GetIpProto()
1919 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001920 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001921 classifierInfo[InPort] = field.GetPort()
1922 log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001923 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05301924 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
salmansiddiqui7ac62132019-08-22 03:58:50 +00001925 log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001926 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001927 classifierInfo[VlanPcp] = field.GetVlanPcp()
1928 log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001929 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001930 classifierInfo[UDPDst] = field.GetUdpDst()
1931 log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001932 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001933 classifierInfo[UDPSrc] = field.GetUdpSrc()
1934 log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001935 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001936 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
1937 log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001938 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001939 classifierInfo[Ipv4Src] = field.GetIpv4Src()
1940 log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001941 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001942 classifierInfo[Metadata] = field.GetTableMetadata()
1943 log.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07001944 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001945 classifierInfo[TunnelID] = field.GetTunnelId()
1946 log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
1947 } else {
1948 log.Errorw("Un supported field type", log.Fields{"type": field.Type})
1949 return
1950 }
1951 }
1952}
1953
1954func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07001955 for _, action := range flows.GetActions(flow) {
1956 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001957 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001958 actionInfo[Output] = out.GetPort()
1959 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001960 } else {
1961 log.Error("Invalid output port in action")
1962 return errors.New("invalid output port in action")
1963 }
Scott Baker355d1742019-10-24 10:57:52 -07001964 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001965 actionInfo[PopVlan] = true
1966 log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001967 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001968 if out := action.GetPush(); out != nil {
1969 if tpid := out.GetEthertype(); tpid != 0x8100 {
1970 log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
1971 } else {
1972 actionInfo[PushVlan] = true
1973 actionInfo[TPID] = tpid
1974 log.Debugw("action-type-push-vlan",
1975 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
1976 }
1977 }
Scott Baker355d1742019-10-24 10:57:52 -07001978 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001979 if out := action.GetSetField(); out != nil {
1980 if field := out.GetField(); field != nil {
1981 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
1982 log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
1983 return errors.New("invalid openflow class")
1984 }
1985 /*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
1986 if ofbField := field.GetOfbField(); ofbField != nil {
1987 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
1988 if vlan := ofbField.GetVlanVid(); vlan != 0 {
1989 actionInfo[VlanVid] = vlan & 0xfff
1990 log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
1991 } else {
1992 log.Error("No Invalid vlan id in set vlan-vid action")
1993 }
1994 } else {
1995 log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
1996 }
1997 }
1998 }
1999 }
2000 } else {
2001 log.Errorw("Un supported action type", log.Fields{"type": action.Type})
2002 return errors.New("un supported action type")
2003 }
2004 }
2005 return nil
2006}
2007
2008func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002009 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002010 log.Debug("Controller bound trap flows, getting inport from tunnelid")
2011 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2012 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002013 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002014 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07002015 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 +00002016 } else {
2017 log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
2018 return errors.New("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
2019 }
2020 }
2021 } else {
2022 log.Debug("Non-Controller flows, getting uniport from tunnelid")
2023 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07002024 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002025 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002026 actionInfo[Output] = uniPort
2027 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 +00002028 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002029 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 +00002030 return errors.New("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid")
2031 }
2032 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2033 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002034 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002035 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07002036 log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[Output].(uint32),
2037 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002038 } else {
2039 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 -07002040 "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002041 return errors.New("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid")
2042 }
2043 }
2044 }
2045 return nil
2046}
Gamze Abakafee36392019-10-03 11:17:24 +00002047
Chaitrashree G S90a17952019-11-14 21:51:21 -05002048func getTpIDFromFlow(flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00002049 /* Metadata 8 bytes:
2050 Most Significant 2 Bytes = Inner VLAN
2051 Next 2 Bytes = Tech Profile ID(TPID)
2052 Least Significant 4 Bytes = Port ID
2053 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
2054 subscriber related flows.
2055 */
2056 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
2057 if metadata == 0 {
Chaitrashree G S90a17952019-11-14 21:51:21 -05002058 log.Error("metadata-is-not-present-in-flow-which-is-mandatory")
2059 return 0, errors.New("metadata-is-not-present-in-flow-which-is-mandatory")
Gamze Abakafee36392019-10-03 11:17:24 +00002060 }
2061 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002062 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00002063}
2064
2065func appendUnique(slice []uint32, item uint32) []uint32 {
2066 for _, sliceElement := range slice {
2067 if sliceElement == item {
2068 return slice
2069 }
2070 }
2071 return append(slice, item)
2072}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302073
2074// getNniIntfID gets nni intf id from the flow classifier/action
2075func getNniIntfID(classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
2076
2077 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
2078 if portType == voltha.Port_PON_OLT {
2079 intfID := IntfIDFromNniPortNum(action[Output].(uint32))
2080 log.Debugw("output Nni IntfID is", log.Fields{"intfid": intfID})
2081 return intfID, nil
2082 } else if portType == voltha.Port_ETHERNET_NNI {
2083 intfID := IntfIDFromNniPortNum(classifier[InPort].(uint32))
2084 log.Debugw("input Nni IntfID is", log.Fields{"intfid": intfID})
2085 return intfID, nil
2086 }
2087 return uint32(0), nil
2088}
2089
2090// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
2091func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32) {
2092 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort}
2093
2094 f.lockCache.Lock()
2095 defer f.lockCache.Unlock()
2096 _, ok := f.packetInGemPort[pktInkey]
2097 if ok {
2098 log.Debugw("pktin key found in cache , no need to update kv as we are assuming both will be in sync",
2099 log.Fields{"pktinkey": pktInkey, "gem": gemPort})
2100 } else {
2101 f.packetInGemPort[pktInkey] = gemPort
2102
2103 f.resourceMgr.UpdateGemPortForPktIn(pktInkey, gemPort)
2104 log.Debugw("pktin key not found in local cache updating cache and kv store", log.Fields{"pktinkey": pktInkey, "gem": gemPort})
2105 }
2106 return
2107}
2108
2109// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
2110func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(intfID uint32, onuID uint32, portNum uint32) {
2111
2112 f.lockCache.Lock()
2113 defer f.lockCache.Unlock()
2114 onugem := f.onuGemInfo[intfID]
2115 for idx, onu := range onugem {
2116 if onu.OnuID == onuID {
2117 for _, uni := range onu.UniPorts {
2118 if uni == portNum {
2119 log.Debugw("uni already in cache, no need to update cache and kv store",
2120 log.Fields{"uni": portNum})
2121 return
2122 }
2123 }
2124 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
2125 f.onuGemInfo[intfID] = onugem
2126 }
2127 }
2128 f.resourceMgr.AddUniPortToOnuInfo(intfID, onuID, portNum)
2129}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302130
2131func (f *OpenOltFlowMgr) loadFlowIDlistForGem(intf uint32) {
2132 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(intf)
2133 if err != nil {
2134 log.Error("Failed to get flowid list per gem", log.Fields{"intf": intf})
2135 return
2136 }
2137 for gem, FlowIDs := range flowIDsList {
2138 gemPK := gemPortKey{intf, uint32(gem)}
2139 f.flowsUsedByGemPort[gemPK] = FlowIDs
2140 }
2141 return
2142}