blob: 67d2a2a17bbad1622d2e43b654752928ae12a6ef [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
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301223//clearResources clears pon resources in kv store and the device
1224func (f *OpenOltFlowMgr) clearResources(flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
1225 gemPortID int32, flowID uint32, flowDirection string,
1226 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001227
Chaitrashree G S90a17952019-11-14 21:51:21 -05001228 tpID, err := getTpIDFromFlow(flow)
1229 if err != nil {
1230 log.Error("metadata-is-not-present-invalid-flow-to-process", log.Fields{"pon": Intf, "onuID": onuID, "uniID": uniID})
1231 return err
1232 }
Gamze Abakafee36392019-10-03 11:17:24 +00001233
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001234 if len(updatedFlows) >= 0 {
1235 // There are still flows referencing the same flow_id.
1236 // So the flow should not be freed yet.
1237 // For ex: Case of HSIA where same flow is shared
1238 // between DS and US.
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301239 f.updateFlowInfoToKVStore(int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001240 if len(updatedFlows) == 0 {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301241 log.Debugw("Releasing flow Id to resource manager", log.Fields{"Intf": Intf, "onuId": onuID, "uniId": uniID, "flowId": flowID})
1242 f.resourceMgr.FreeFlowID(Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001243
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301244 uni := getUniPortPath(Intf, onuID, uniID)
1245 tpPath := f.getTPpath(Intf, uni, tpID)
Gamze Abakafee36392019-10-03 11:17:24 +00001246 log.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301247 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(tpID, tpPath)
Gamze Abakafee36392019-10-03 11:17:24 +00001248 if err != nil { // This should not happen, something wrong in KV backend transaction
1249 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": 20, "path": tpPath})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301250 return err
Gamze Abakafee36392019-10-03 11:17:24 +00001251 }
1252 if techprofileInst == nil {
1253 log.Errorw("Tech-profile-instance-does-not-exist-in-KV Store", log.Fields{"tpPath": tpPath})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301254 return err
Gamze Abakafee36392019-10-03 11:17:24 +00001255 }
1256
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301257 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00001258 if f.isGemPortUsedByAnotherFlow(gemPK) {
1259 flowIDs := f.flowsUsedByGemPort[gemPK]
1260 for i, flowIDinMap := range flowIDs {
1261 if flowIDinMap == flowID {
1262 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301263 // everytime flowsUsedByGemPort cache is updated the same should be updated
1264 // in kv store by calling UpdateFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001265 f.flowsUsedByGemPort[gemPK] = flowIDs
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301266 f.resourceMgr.UpdateFlowIDsForGem(Intf, uint32(gemPortID), flowIDs)
Gamze Abakafee36392019-10-03 11:17:24 +00001267 break
1268 }
1269 }
1270 log.Debugw("Gem port id is still used by other flows", log.Fields{"gemPortID": gemPortID, "usedByFlows": flowIDs})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301271 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00001272 }
Gamze Abakafee36392019-10-03 11:17:24 +00001273 log.Debugf("Gem port id %d is not used by another flow - releasing the gem port", gemPortID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301274 f.resourceMgr.RemoveGemPortIDForOnu(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001275 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1276 // 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 +05301277 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(uint32(gemPortID), Intf)
Gamze Abakafee36392019-10-03 11:17:24 +00001278 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301279 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1280 // by calling DeleteFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001281 delete(f.flowsUsedByGemPort, gemPK)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301282 f.resourceMgr.DeleteFlowIDsForGem(Intf, uint32(gemPortID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301283 f.resourceMgr.FreeGemPortID(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001284 f.onuIdsLock.Unlock()
1285
Girish Gowdra54934262019-11-13 14:19:55 +05301286 ok, _ := f.isTechProfileUsedByAnotherGem(Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001287 if !ok {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301288 f.resourceMgr.RemoveTechProfileIDForOnu(Intf, uint32(onuID), uint32(uniID), tpID)
1289 f.RemoveSchedulerQueues(schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1290 f.RemoveSchedulerQueues(schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1291 f.DeleteTechProfileInstance(Intf, uint32(onuID), uint32(uniID), "", tpID)
1292 f.resourceMgr.FreeAllocID(Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
Gamze Abakafee36392019-10-03 11:17:24 +00001293 // TODO: Send a "Delete TechProfile" message to ONU to do its own clean up on ONU OMCI stack
1294 }
1295 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001296 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301297 return nil
1298}
1299
1300func (f *OpenOltFlowMgr) clearFlowFromResourceManager(flow *ofp.OfpFlowStats, flowDirection string) {
1301
1302 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowDirection": flowDirection, "flow": *flow})
1303 var updatedFlows []rsrcMgr.FlowInfo
1304 var flowID uint32
1305 var onuID, uniID int32
1306 classifierInfo := make(map[string]interface{})
1307
1308 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
1309 if err != nil {
1310 log.Error(err)
1311 return
1312 }
1313 onuID = int32(onu)
1314 uniID = int32(uni)
1315
1316 for _, field := range flows.GetOfbFields(flow) {
1317 if field.Type == flows.IP_PROTO {
1318 classifierInfo[IPProto] = field.GetIpProto()
1319 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
1320 }
1321 }
1322 log.Debugw("Extracted access info from flow to be deleted",
1323 log.Fields{"ponIntf": Intf, "onuID": onuID, "uniID": uniID})
1324
1325 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1326 onuID = -1
1327 uniID = -1
1328 log.Debug("Trap on nni flow set oni, uni to -1")
1329 Intf = IntfIDFromNniPortNum(inPort)
1330 }
1331 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(Intf, onuID, uniID)
1332 for _, flowID = range flowIds {
1333 flowInfo := f.resourceMgr.GetFlowIDInfo(Intf, onuID, uniID, flowID)
1334 if flowInfo == nil {
1335 log.Debugw("No FlowInfo found found in KV store",
1336 log.Fields{"Intf": Intf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1337 return
1338 }
1339 updatedFlows = nil
1340 for _, flow := range *flowInfo {
1341 updatedFlows = append(updatedFlows, flow)
1342 }
1343
1344 for i, storedFlow := range updatedFlows {
1345 if flow.Id == storedFlow.LogicalFlowID {
1346 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
1347 log.Debugw("Flow to be deleted", log.Fields{"flow": storedFlow})
1348 if ok := f.removeFlowFromDevice(&removeFlowMessage); ok {
1349 log.Debug("Flow removed from device successfully")
1350 //Remove the Flow from FlowInfo
1351 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1352 err = f.clearResources(flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
1353 flowID, flowDirection, portNum, updatedFlows)
1354 if err != nil {
1355 log.Error("Failed to clear resources for flow", log.Fields{"flow": storedFlow})
1356 return
1357 }
1358 } else {
1359 log.Error("Failed to remove flow from device")
1360 return
1361 }
1362 }
1363 }
1364 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001365}
1366
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001367//RemoveFlow removes the flow from the device
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001368func (f *OpenOltFlowMgr) RemoveFlow(flow *ofp.OfpFlowStats) {
1369 log.Debugw("Removing Flow", log.Fields{"flow": flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301370 var direction string
1371 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001372
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301373 for _, action := range flows.GetActions(flow) {
1374 if action.Type == flows.OUTPUT {
1375 if out := action.GetOutput(); out != nil {
1376 actionInfo[Output] = out.GetPort()
1377 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
1378 } else {
1379 log.Error("Invalid output port in action")
1380 return
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001381 }
1382 }
1383 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301384 if IsUpstream(actionInfo[Output].(uint32)) {
1385 direction = Upstream
1386 } else {
1387 direction = Downstream
1388 }
1389
1390 f.clearFlowFromResourceManager(flow, direction) //TODO: Take care of the limitations
1391
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001392 return
1393}
1394
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001395// AddFlow add flow to device
Manikkaraj kb1d51442019-07-23 10:41:02 -04001396func (f *OpenOltFlowMgr) AddFlow(flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001397 classifierInfo := make(map[string]interface{})
1398 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001399 var UsMeterID uint32
1400 var DsMeterID uint32
1401
1402 log.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001403 formulateClassifierInfoFromFlow(classifierInfo, flow)
1404
1405 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
1406 if err != nil {
1407 // Error logging is already done in the called function
1408 // So just return in case of error
1409 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301410 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001411
manikkaraj k17652a72019-05-06 09:06:36 -04001412 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00001413 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
1414 if err != nil {
1415 // error if any, already logged in the called function
1416 return
manikkaraj k17652a72019-05-06 09:06:36 -04001417 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001418
David K. Bainbridge82efc492019-09-04 09:57:11 -07001419 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[Output]})
1420 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00001421
Humera Kouser94d7a842019-08-25 19:04:32 -04001422 if ethType, ok := classifierInfo[EthType]; ok {
1423 if ethType.(uint32) == LldpEthType {
1424 log.Info("Adding LLDP flow")
1425 f.addLLDPFlow(flow, portNo)
1426 return
1427 }
1428 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001429 if ipProto, ok := classifierInfo[IPProto]; ok {
1430 if ipProto.(uint32) == IPProtoDhcp {
1431 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001432 if udpSrc.(uint32) == uint32(67) {
1433 log.Debug("trap-dhcp-from-nni-flow")
1434 f.addDHCPTrapFlowOnNNI(flow, classifierInfo, portNo)
1435 return
1436 }
1437 }
1438 }
1439 }
A R Karthick1f85b802019-10-11 05:06:05 +00001440
1441 f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301442 f.resourceMgr.AddUniPortToOnuInfo(intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00001443
Chaitrashree G S90a17952019-11-14 21:51:21 -05001444 TpID, err := getTpIDFromFlow(flow)
1445 if err != nil {
1446 log.Error("metadata-is-not-present-invalid-flow-to-process", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1447 return
1448 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001449 log.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001450 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07001451 UsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001452 log.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
1453 } else {
Scott Baker355d1742019-10-24 10:57:52 -07001454 DsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001455 log.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
1456
1457 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001458 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001459}
1460
1461//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04001462func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001463
1464 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301465 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001466 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301467 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301468 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301469 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04001470
Manikkaraj kb1d51442019-07-23 10:41:02 -04001471 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001472 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
manikkaraj k17652a72019-05-06 09:06:36 -04001473 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
1474 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1475 tpDownloadMsg,
1476 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
1477 f.deviceHandler.deviceType,
1478 onuDevice.Type,
1479 onuDevice.Id,
1480 onuDevice.ProxyAddress.DeviceId, "")
1481 if sendErr != nil {
1482 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1483 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1484 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1485 return sendErr
1486 }
1487 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05301488 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301489}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001490
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301491//UpdateOnuInfo function adds onu info to cache and kvstore
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001492func (f *OpenOltFlowMgr) UpdateOnuInfo(intfID uint32, onuID uint32, serialNum string) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301493
1494 f.lockCache.Lock()
1495 defer f.lockCache.Unlock()
1496 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
1497 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
1498 if err := f.resourceMgr.AddOnuInfo(intfID, onu); err != nil {
1499 log.Errorw("failed to add onu info", log.Fields{"onu": onu})
1500 return
1501 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001502 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
1503}
1504
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301505//addGemPortToOnuInfoMap function adds GEMport to ONU map
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001506func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(intfID uint32, onuID uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301507 f.lockCache.Lock()
1508 defer f.lockCache.Unlock()
1509 onugem := f.onuGemInfo[intfID]
1510 // update the gem to the local cache as well as to kv strore
1511 for idx, onu := range onugem {
1512 if onu.OnuID == onuID {
1513 // check if gem already exists , else update the cache and kvstore
1514 for _, gem := range onu.GemPorts {
1515 if gem == gemPort {
1516 log.Debugw("Gem already in cache, no need to update cache and kv store",
1517 log.Fields{"gem": gemPort})
1518 return
1519 }
1520 }
1521 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
1522 f.onuGemInfo[intfID] = onugem
1523 }
1524 }
1525 err := f.resourceMgr.AddGemToOnuGemInfo(intfID, onuID, gemPort)
1526 if err != nil {
1527 log.Errorw("Failed to add gem to onu", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001528 return
1529 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001530}
1531
1532// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001533
1534//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
1535func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301536
1537 f.lockCache.Lock()
1538 defer f.lockCache.Unlock()
1539
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001540 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 +05301541 // get onuid from the onugem info cache
1542 onugem := f.onuGemInfo[intfID]
1543 for _, onu := range onugem {
1544 for _, gem := range onu.GemPorts {
1545 if gem == gemPortID {
1546 return onu.OnuID, nil
1547 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001548 }
1549 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001550 log.Errorw("onuid is not found", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPort": gemPortID})
1551 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 -04001552}
1553
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001554//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
1555func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001556 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001557 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001558 var err error
1559
1560 if packetIn.IntfType == "pon" {
1561 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001562 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001563 log.Errorw("Unable to get ONU ID from GEM/PON port", log.Fields{"pon port": packetIn.IntfId, "gemport": packetIn.GemportId})
1564 return logicalPortNum, err
1565 }
1566 if packetIn.PortNo != 0 {
1567 logicalPortNum = packetIn.PortNo
1568 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001569 uniID := uint32(0) // FIXME - multi-uni support
1570 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001571 }
1572 // 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 +05301573 f.UpdateGemPortForPktIn(packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001574 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001575 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001576 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001577 log.Debugw("Retrieved logicalport from packet-in", log.Fields{
1578 "logicalPortNum": logicalPortNum,
1579 "IntfType": packetIn.IntfType,
1580 "packet": hex.EncodeToString(packetIn.Pkt),
1581 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001582 return logicalPortNum, nil
1583}
1584
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001585//GetPacketOutGemPortID returns gemPortId
1586func (f *OpenOltFlowMgr) GetPacketOutGemPortID(intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
1587 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001588 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301589
1590 f.lockCache.Lock()
1591 defer f.lockCache.Unlock()
1592 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum}
1593
1594 gemPortID, ok := f.packetInGemPort[pktInkey]
1595 if ok {
1596 log.Debugw("Found gemport for pktin key", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1597 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001598 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301599 //If gem is not found in cache try to get it from kv store, if found in kv store, update the cache and return.
1600 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(intfID, onuID, portNum)
1601 if err == nil {
1602 if gemPortID != 0 {
1603 f.packetInGemPort[pktInkey] = gemPortID
1604 log.Debugw("Found gem port from kv store and updating cache with gemport",
1605 log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1606 return gemPortID, nil
1607 }
1608 }
1609 log.Errorw("Failed to get gemport", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1610 return uint32(0), err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001611}
1612
Manikkaraj kb1d51442019-07-23 10:41:02 -04001613func installFlowOnAllGemports(
1614 f1 func(intfId uint32, onuId uint32, uniId uint32,
1615 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
1616 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32),
1617 f2 func(intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301618 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
1619 classifier map[string]interface{}, action map[string]interface{}),
Manikkaraj kb1d51442019-07-23 10:41:02 -04001620 args map[string]uint32,
1621 classifier map[string]interface{}, action map[string]interface{},
1622 logicalFlow *ofp.OfpFlowStats,
1623 gemPorts []uint32,
1624 FlowType string,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001625 vlanID ...uint32) {
1626 log.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
1627 for _, gemPortID := range gemPorts {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001628 if FlowType == HsiaFlow || FlowType == DhcpFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001629 f1(args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001630 } else if FlowType == EapolFlow {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301631 f2(args["intfId"], args["onuId"], args["uniId"], args["portNo"], logicalFlow, args["allocId"], gemPortID, vlanID[0], classifier, action)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001632 } else {
1633 log.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
1634 return
1635 }
1636 }
1637}
1638
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001639func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
1640 log.Debug("Adding trap-dhcp-of-nni-flow")
1641 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001642 classifier[PacketTagType] = DoubleTag
1643 action[TrapToHost] = true
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301644 var err error
1645 var networkInterfaceID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001646 /* We manage flowId resource pool on per PON port basis.
1647 Since this situation is tricky, as a hack, we pass the NNI port
1648 index (network_intf_id) as PON port Index for the flowId resource
1649 pool. Also, there is no ONU Id available for trapping DHCP packets
1650 on NNI port, use onu_id as -1 (invalid)
1651 ****************** CAVEAT *******************
1652 This logic works if the NNI Port Id falls within the same valid
1653 range of PON Port Ids. If this doesn't work for some OLT Vendor
1654 we need to have a re-look at this.
1655 *********************************************
1656 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001657 onuID := -1
1658 uniID := -1
1659 gemPortID := -1
1660 allocID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301661 networkInterfaceID, err = getNniIntfID(classifier, action)
1662 if err != nil {
1663 log.Error("Failed to get nniIntf ID")
1664 return
1665 }
1666
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001667 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301668 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001669 log.Debug("Flow-exists--not-re-adding")
1670 return
1671 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301672 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001673 if err != nil {
1674 log.Errorw("Flow id unavailable for DHCP traponNNI flow", log.Fields{"error": err})
1675 return
1676 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001677 var classifierProto *openoltpb2.Classifier
1678 var actionProto *openoltpb2.Action
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001679 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
1680 log.Error("Error in making classifier protobuf for dhcp trap on nni flow")
1681 return
1682 }
1683 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1684 if actionProto = makeOpenOltActionField(action); actionProto == nil {
1685 log.Error("Error in making action protobuf for dhcp trap on nni flow")
1686 return
1687 }
1688 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001689 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1690 OnuId: int32(onuID), // OnuId not required
1691 UniId: int32(uniID), // UniId not used
1692 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001693 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001694 AllocId: int32(allocID), // AllocId not used
1695 NetworkIntfId: int32(networkInterfaceID),
1696 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001697 Classifier: classifierProto,
1698 Action: actionProto,
1699 Priority: int32(logicalFlow.Priority),
1700 Cookie: logicalFlow.Cookie,
1701 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001702 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001703 log.Debug("DHCP trap on NNI flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301704 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001705 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1706 int32(onuID),
1707 int32(uniID),
1708 flowID, flowsToKVStore); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001709 log.Errorw("Error uploading DHCP DL flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1710 }
1711 }
1712 return
1713}
salmansiddiqui7ac62132019-08-22 03:58:50 +00001714
1715func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
1716 if MeterID == 0 { // This should never happen
1717 log.Error("Invalid meter id")
1718 return "", errors.New("invalid meter id")
1719 }
1720 if Dir == tp_pb.Direction_UPSTREAM {
1721 return "upstream", nil
1722 } else if Dir == tp_pb.Direction_DOWNSTREAM {
1723 return "downstream", nil
1724 }
1725 return "", nil
1726}
1727
1728func (f *OpenOltFlowMgr) checkAndAddFlow(args map[string]uint32, classifierInfo map[string]interface{},
Gamze Abakafee36392019-10-03 11:17:24 +00001729 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst *tp.TechProfile, gemPorts []uint32,
1730 TpID uint32, uni string) {
1731 var gemPort uint32
1732 intfID := args[IntfID]
1733 onuID := args[OnuID]
1734 uniID := args[UniID]
1735 portNo := args[PortNo]
1736 allocID := TpInst.UsScheduler.AllocID
salmansiddiqui7ac62132019-08-22 03:58:50 +00001737 if ipProto, ok := classifierInfo[IPProto]; ok {
1738 if ipProto.(uint32) == IPProtoDhcp {
1739 log.Info("Adding DHCP flow")
1740 if pcp, ok := classifierInfo[VlanPcp]; ok {
1741 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1742 tp_pb.Direction_UPSTREAM,
1743 pcp.(uint32))
1744 //Adding DHCP upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001745 f.addDHCPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001746 } else {
1747 //Adding DHCP upstream flow to all gemports
1748 installFlowOnAllGemports(f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, DhcpFlow)
1749 }
1750
1751 } else if ipProto == IgmpProto {
1752 log.Info("igmp flow add ignored, not implemented yet")
1753 return
1754 } else {
1755 log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
1756 return
1757 }
1758 } else if ethType, ok := classifierInfo[EthType]; ok {
1759 if ethType.(uint32) == EapEthType {
1760 log.Info("Adding EAPOL flow")
1761 var vlanID uint32
1762 if val, ok := classifierInfo[VlanVid]; ok {
1763 vlanID = (val.(uint32)) & VlanvIDMask
1764 } else {
1765 vlanID = DefaultMgmtVlan
1766 }
1767 if pcp, ok := classifierInfo[VlanPcp]; ok {
1768 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1769 tp_pb.Direction_UPSTREAM,
1770 pcp.(uint32))
1771
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301772 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID, gemPort, vlanID, classifierInfo, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001773 } else {
1774 installFlowOnAllGemports(nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, EapolFlow, vlanID)
1775 }
1776 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001777 } else if _, ok := actionInfo[PushVlan]; ok {
1778 log.Info("Adding upstream data rule")
1779 if pcp, ok := classifierInfo[VlanPcp]; ok {
1780 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
1781 tp_pb.Direction_UPSTREAM,
1782 pcp.(uint32))
1783 //Adding HSIA upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001784 f.addUpstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001785 } else {
1786 //Adding HSIA upstream flow to all gemports
1787 installFlowOnAllGemports(f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1788 }
1789 } else if _, ok := actionInfo[PopVlan]; ok {
1790 log.Info("Adding Downstream data rule")
1791 if pcp, ok := classifierInfo[VlanPcp]; ok {
1792 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05001793 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001794 pcp.(uint32))
1795 //Adding HSIA downstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00001796 f.addDownstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00001797 } else {
1798 //Adding HSIA downstream flow to all gemports
1799 installFlowOnAllGemports(f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
1800 }
1801 } else {
1802 log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
1803 return
1804 }
1805 // Send Techprofile download event to child device in go routine as it takes time
1806 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, TpID)
1807}
1808
Gamze Abakafee36392019-10-03 11:17:24 +00001809func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
1810 flowIDList := f.flowsUsedByGemPort[gemPK]
1811 if len(flowIDList) > 1 {
1812 return true
1813 }
1814 return false
1815}
1816
Girish Gowdra54934262019-11-13 14:19:55 +05301817func (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 +00001818 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ponIntf, onuID, uniID)
1819 tpGemPorts := tpInst.UpstreamGemPortAttributeList
1820 for _, currentGemPort := range currentGemPorts {
1821 for _, tpGemPort := range tpGemPorts {
1822 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
1823 return true, currentGemPort
1824 }
1825 }
1826 }
Girish Gowdra54934262019-11-13 14:19:55 +05301827 if tpInst.InstanceCtrl.Onu == "single-instance" {
1828 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
1829 f.resourceMgr.RemoveTechProfileIDForOnu(ponIntf, uint32(onuID), uint32(uniID), tpID)
1830 f.DeleteTechProfileInstance(ponIntf, uint32(onuID), uint32(uniID), "", tpID)
1831
1832 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
1833 // still be used on other uni ports.
1834 // So, we need to check and make sure that no other gem port is referring to the given TP ID
1835 // on any other uni port.
1836 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(tpID, ponIntf, onuID)
1837 for i := 0; i < len(tpInstances); i++ {
1838 tpI := tpInstances[i]
1839 tpGemPorts := tpI.UpstreamGemPortAttributeList
1840 for _, currentGemPort := range currentGemPorts {
1841 for _, tpGemPort := range tpGemPorts {
1842 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
1843 log.Debugw("tech-profile-is-in-use-by-gem", log.Fields{"gemPort": currentGemPort})
1844 return true, currentGemPort
1845 }
1846 }
1847 }
1848 }
1849 }
1850 log.Debug("tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00001851 return false, 0
1852}
1853
salmansiddiqui7ac62132019-08-22 03:58:50 +00001854func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07001855 for _, field := range flows.GetOfbFields(flow) {
1856 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001857 classifierInfo[EthType] = field.GetEthType()
1858 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001859 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001860 classifierInfo[IPProto] = field.GetIpProto()
1861 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001862 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001863 classifierInfo[InPort] = field.GetPort()
1864 log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001865 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05301866 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
salmansiddiqui7ac62132019-08-22 03:58:50 +00001867 log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001868 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001869 classifierInfo[VlanPcp] = field.GetVlanPcp()
1870 log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001871 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001872 classifierInfo[UDPDst] = field.GetUdpDst()
1873 log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001874 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001875 classifierInfo[UDPSrc] = field.GetUdpSrc()
1876 log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001877 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001878 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
1879 log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001880 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001881 classifierInfo[Ipv4Src] = field.GetIpv4Src()
1882 log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001883 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001884 classifierInfo[Metadata] = field.GetTableMetadata()
1885 log.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07001886 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001887 classifierInfo[TunnelID] = field.GetTunnelId()
1888 log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
1889 } else {
1890 log.Errorw("Un supported field type", log.Fields{"type": field.Type})
1891 return
1892 }
1893 }
1894}
1895
1896func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07001897 for _, action := range flows.GetActions(flow) {
1898 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001899 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001900 actionInfo[Output] = out.GetPort()
1901 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001902 } else {
1903 log.Error("Invalid output port in action")
1904 return errors.New("invalid output port in action")
1905 }
Scott Baker355d1742019-10-24 10:57:52 -07001906 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001907 actionInfo[PopVlan] = true
1908 log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07001909 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001910 if out := action.GetPush(); out != nil {
1911 if tpid := out.GetEthertype(); tpid != 0x8100 {
1912 log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
1913 } else {
1914 actionInfo[PushVlan] = true
1915 actionInfo[TPID] = tpid
1916 log.Debugw("action-type-push-vlan",
1917 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
1918 }
1919 }
Scott Baker355d1742019-10-24 10:57:52 -07001920 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001921 if out := action.GetSetField(); out != nil {
1922 if field := out.GetField(); field != nil {
1923 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
1924 log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
1925 return errors.New("invalid openflow class")
1926 }
1927 /*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
1928 if ofbField := field.GetOfbField(); ofbField != nil {
1929 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
1930 if vlan := ofbField.GetVlanVid(); vlan != 0 {
1931 actionInfo[VlanVid] = vlan & 0xfff
1932 log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
1933 } else {
1934 log.Error("No Invalid vlan id in set vlan-vid action")
1935 }
1936 } else {
1937 log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
1938 }
1939 }
1940 }
1941 }
1942 } else {
1943 log.Errorw("Un supported action type", log.Fields{"type": action.Type})
1944 return errors.New("un supported action type")
1945 }
1946 }
1947 return nil
1948}
1949
1950func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001951 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001952 log.Debug("Controller bound trap flows, getting inport from tunnelid")
1953 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
1954 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001955 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001956 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07001957 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 +00001958 } else {
1959 log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1960 return errors.New("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
1961 }
1962 }
1963 } else {
1964 log.Debug("Non-Controller flows, getting uniport from tunnelid")
1965 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07001966 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001967 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001968 actionInfo[Output] = uniPort
1969 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 +00001970 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001971 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 +00001972 return errors.New("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid")
1973 }
1974 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
1975 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07001976 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001977 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07001978 log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[Output].(uint32),
1979 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001980 } else {
1981 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 -07001982 "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001983 return errors.New("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid")
1984 }
1985 }
1986 }
1987 return nil
1988}
Gamze Abakafee36392019-10-03 11:17:24 +00001989
Chaitrashree G S90a17952019-11-14 21:51:21 -05001990func getTpIDFromFlow(flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00001991 /* Metadata 8 bytes:
1992 Most Significant 2 Bytes = Inner VLAN
1993 Next 2 Bytes = Tech Profile ID(TPID)
1994 Least Significant 4 Bytes = Port ID
1995 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
1996 subscriber related flows.
1997 */
1998 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
1999 if metadata == 0 {
Chaitrashree G S90a17952019-11-14 21:51:21 -05002000 log.Error("metadata-is-not-present-in-flow-which-is-mandatory")
2001 return 0, errors.New("metadata-is-not-present-in-flow-which-is-mandatory")
Gamze Abakafee36392019-10-03 11:17:24 +00002002 }
2003 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002004 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00002005}
2006
2007func appendUnique(slice []uint32, item uint32) []uint32 {
2008 for _, sliceElement := range slice {
2009 if sliceElement == item {
2010 return slice
2011 }
2012 }
2013 return append(slice, item)
2014}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302015
2016// getNniIntfID gets nni intf id from the flow classifier/action
2017func getNniIntfID(classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
2018
2019 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
2020 if portType == voltha.Port_PON_OLT {
2021 intfID := IntfIDFromNniPortNum(action[Output].(uint32))
2022 log.Debugw("output Nni IntfID is", log.Fields{"intfid": intfID})
2023 return intfID, nil
2024 } else if portType == voltha.Port_ETHERNET_NNI {
2025 intfID := IntfIDFromNniPortNum(classifier[InPort].(uint32))
2026 log.Debugw("input Nni IntfID is", log.Fields{"intfid": intfID})
2027 return intfID, nil
2028 }
2029 return uint32(0), nil
2030}
2031
2032// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
2033func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32) {
2034 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort}
2035
2036 f.lockCache.Lock()
2037 defer f.lockCache.Unlock()
2038 _, ok := f.packetInGemPort[pktInkey]
2039 if ok {
2040 log.Debugw("pktin key found in cache , no need to update kv as we are assuming both will be in sync",
2041 log.Fields{"pktinkey": pktInkey, "gem": gemPort})
2042 } else {
2043 f.packetInGemPort[pktInkey] = gemPort
2044
2045 f.resourceMgr.UpdateGemPortForPktIn(pktInkey, gemPort)
2046 log.Debugw("pktin key not found in local cache updating cache and kv store", log.Fields{"pktinkey": pktInkey, "gem": gemPort})
2047 }
2048 return
2049}
2050
2051// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
2052func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(intfID uint32, onuID uint32, portNum uint32) {
2053
2054 f.lockCache.Lock()
2055 defer f.lockCache.Unlock()
2056 onugem := f.onuGemInfo[intfID]
2057 for idx, onu := range onugem {
2058 if onu.OnuID == onuID {
2059 for _, uni := range onu.UniPorts {
2060 if uni == portNum {
2061 log.Debugw("uni already in cache, no need to update cache and kv store",
2062 log.Fields{"uni": portNum})
2063 return
2064 }
2065 }
2066 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
2067 f.onuGemInfo[intfID] = onugem
2068 }
2069 }
2070 f.resourceMgr.AddUniPortToOnuInfo(intfID, onuID, portNum)
2071}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302072
2073func (f *OpenOltFlowMgr) loadFlowIDlistForGem(intf uint32) {
2074 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(intf)
2075 if err != nil {
2076 log.Error("Failed to get flowid list per gem", log.Fields{"intf": intf})
2077 return
2078 }
2079 for gem, FlowIDs := range flowIDsList {
2080 gemPK := gemPortKey{intf, uint32(gem)}
2081 f.flowsUsedByGemPort[gemPK] = FlowIDs
2082 }
2083 return
2084}