blob: 337680934347320666c3cb148e2c3c4e5f716d7c [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"
Girish Gowdra3d633032019-12-10 16:37:05 +053029 "time"
Manikkaraj kb1d51442019-07-23 10:41:02 -040030
Scott Baker51290152019-10-24 14:23:20 -070031 "github.com/opencord/voltha-lib-go/v2/pkg/flows"
32 "github.com/opencord/voltha-lib-go/v2/pkg/log"
33 tp "github.com/opencord/voltha-lib-go/v2/pkg/techprofile"
Manikkaraj k884c1242019-04-11 16:26:42 +053034 rsrcMgr "github.com/opencord/voltha-openolt-adapter/adaptercore/resourcemanager"
Scott Bakerc6e54cb2019-11-04 09:31:25 -080035 "github.com/opencord/voltha-protos/v2/go/common"
36 ic "github.com/opencord/voltha-protos/v2/go/inter_container"
37 ofp "github.com/opencord/voltha-protos/v2/go/openflow_13"
38 openoltpb2 "github.com/opencord/voltha-protos/v2/go/openolt"
39 tp_pb "github.com/opencord/voltha-protos/v2/go/tech_profile"
40 "github.com/opencord/voltha-protos/v2/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040041
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -040042 //deepcopy "github.com/getlantern/deepcopy"
Girish Gowdra3d633032019-12-10 16:37:05 +053043 "github.com/EagleChen/mapmutex"
Daniele Rossi22db98e2019-07-11 11:50:00 +000044 "google.golang.org/grpc/codes"
45 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053046)
47
48const (
49 // Flow categories
manikkaraj kbf256be2019-03-25 00:13:48 +053050
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070051 //HsiaFlow flow category
52 HsiaFlow = "HSIA_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053053
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070054 //EapolFlow flow category
55 EapolFlow = "EAPOL_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053056
Manikkaraj kb1d51442019-07-23 10:41:02 -040057 //DhcpFlow flow category
58 DhcpFlow = "DHCP_FLOW"
59
Esin Karamanae41e2b2019-12-17 18:13:13 +000060 //IgmpFlow flow category
61 IgmpFlow = "IGMP_FLOW"
62
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070063 //IPProtoDhcp flow category
64 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053065
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070066 //IPProtoIgmp flow category
67 IPProtoIgmp = 2
68
69 //EapEthType eapethtype value
70 EapEthType = 0x888e
71 //LldpEthType lldp ethtype value
72 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000073 //IPv4EthType IPv4 ethernet type value
74 IPv4EthType = 0x800
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070075
76 //IgmpProto proto value
77 IgmpProto = 2
manikkaraj kbf256be2019-03-25 00:13:48 +053078
79 //FIXME - see also BRDCM_DEFAULT_VLAN in broadcom_onu.py
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070080
Humera Kouser94d7a842019-08-25 19:04:32 -040081 //ReservedVlan Transparent Vlan
David K. Bainbridge82efc492019-09-04 09:57:11 -070082 ReservedVlan = 4095
Harsh Awasthiea45af72019-08-26 02:39:00 -040083
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070084 //DefaultMgmtVlan default vlan value
85 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053086
manikkaraj kbf256be2019-03-25 00:13:48 +053087 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070088
David K. Bainbridge82efc492019-09-04 09:57:11 -070089 //Upstream constant
90 Upstream = "upstream"
91 //Downstream constant
92 Downstream = "downstream"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070093 //PacketTagType constant
94 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070095 //Untagged constant
96 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070097 //SingleTag constant
98 SingleTag = "single_tag"
99 //DoubleTag constant
100 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +0530101
102 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700103
104 //EthType constant
105 EthType = "eth_type"
106 //TPID constant
107 TPID = "tpid"
108 //IPProto constant
109 IPProto = "ip_proto"
110 //InPort constant
111 InPort = "in_port"
112 //VlanVid constant
113 VlanVid = "vlan_vid"
114 //VlanPcp constant
115 VlanPcp = "vlan_pcp"
116
117 //UDPDst constant
118 UDPDst = "udp_dst"
119 //UDPSrc constant
120 UDPSrc = "udp_src"
121 //Ipv4Dst constant
122 Ipv4Dst = "ipv4_dst"
123 //Ipv4Src constant
124 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700125 //Metadata constant
126 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700127 //TunnelID constant
128 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700129 //Output constant
130 Output = "output"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700131 // Actions
132
133 //PopVlan constant
134 PopVlan = "pop_vlan"
135 //PushVlan constant
136 PushVlan = "push_vlan"
137 //TrapToHost constant
138 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400139 //MaxMeterBand constant
140 MaxMeterBand = 2
141 //VlanPCPMask contant
142 VlanPCPMask = 0xFF
143 //VlanvIDMask constant
144 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000145 //IntfID constant
146 IntfID = "intfId"
147 //OnuID constant
148 OnuID = "onuId"
149 //UniID constant
150 UniID = "uniId"
151 //PortNo constant
152 PortNo = "portNo"
153 //AllocID constant
154 AllocID = "allocId"
manikkaraj kbf256be2019-03-25 00:13:48 +0530155)
156
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400157type gemPortKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700158 intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400159 gemPort uint32
160}
161
Girish Gowdra3d633032019-12-10 16:37:05 +0530162type pendingFlowDeleteKey struct {
163 intfID uint32
164 onuID uint32
165 uniID uint32
166}
167
168type tpLockKey struct {
169 intfID uint32
170 onuID uint32
171 uniID uint32
172}
173
Gamze Abakafee36392019-10-03 11:17:24 +0000174type schedQueue struct {
175 direction tp_pb.Direction
176 intfID uint32
177 onuID uint32
178 uniID uint32
179 tpID uint32
180 uniPort uint32
181 tpInst *tp.TechProfile
182 meterID uint32
183 flowMetadata *voltha.FlowMetadata
184}
185
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700186//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530187type OpenOltFlowMgr struct {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000188 techprofile map[uint32]tp.TechProfileIf
Gamze Abakafee36392019-10-03 11:17:24 +0000189 deviceHandler *DeviceHandler
190 resourceMgr *rsrcMgr.OpenOltResourceMgr
Gamze Abakafee36392019-10-03 11:17:24 +0000191 onuIdsLock sync.RWMutex
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530192 flowsUsedByGemPort map[gemPortKey][]uint32 //gem port id to flow ids
193 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
194 onuGemInfo map[uint32][]rsrcMgr.OnuGemInfo //onu, gem and uni info local cache
195 lockCache sync.RWMutex
Girish Gowdra3d633032019-12-10 16:37:05 +0530196 pendingFlowDelete sync.Map
197 // The mapmutex.Mutex can be fine tuned to use mapmutex.NewCustomizedMapMutex
198 perUserFlowHandleLock *mapmutex.Mutex
manikkaraj kbf256be2019-03-25 00:13:48 +0530199}
200
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700201//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530202func NewFlowManager(dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
manikkaraj kbf256be2019-03-25 00:13:48 +0530203 log.Info("Initializing flow manager")
204 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530205 var err error
206 var idx uint32
207
manikkaraj kbf256be2019-03-25 00:13:48 +0530208 flowMgr.deviceHandler = dh
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530209 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000210 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530211 if err = flowMgr.populateTechProfilePerPonPort(); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530212 log.Error("Error while populating tech profile mgr\n")
213 return nil
214 }
William Kurkian740a09c2019-10-23 17:07:38 -0400215 flowMgr.onuIdsLock = sync.RWMutex{}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530216 flowMgr.flowsUsedByGemPort = make(map[gemPortKey][]uint32)
217 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
218 flowMgr.onuGemInfo = make(map[uint32][]rsrcMgr.OnuGemInfo)
219 ponPorts := rMgr.DevInfo.GetPonPorts()
220 //Load the onugem info cache from kv store on flowmanager start
221 for idx = 0; idx < ponPorts; idx++ {
222 if flowMgr.onuGemInfo[idx], err = rMgr.GetOnuGemInfo(idx); err != nil {
223 log.Error("Failed to load onu gem info cache")
224 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530225 //Load flowID list per gem map per interface from the kvstore.
226 flowMgr.loadFlowIDlistForGem(idx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530227 }
228 flowMgr.lockCache = sync.RWMutex{}
Girish Gowdra3d633032019-12-10 16:37:05 +0530229 flowMgr.pendingFlowDelete = sync.Map{}
230 flowMgr.perUserFlowHandleLock = mapmutex.NewMapMutex()
manikkaraj kbf256be2019-03-25 00:13:48 +0530231 log.Info("Initialization of flow manager success!!")
232 return &flowMgr
233}
234
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700235func (f *OpenOltFlowMgr) generateStoredFlowID(flowID uint32, direction string) (uint64, error) {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700236 if direction == Upstream {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400237 log.Debug("upstream flow, shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700238 return 0x1<<15 | uint64(flowID), nil
David K. Bainbridge82efc492019-09-04 09:57:11 -0700239 } else if direction == Downstream {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400240 log.Debug("downstream flow, not shifting id")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700241 return uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400242 } else {
243 log.Debug("Unrecognized direction")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700244 return 0, fmt.Errorf("unrecognized direction %s", direction)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400245 }
246}
247
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700248func (f *OpenOltFlowMgr) registerFlow(flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400249 log.Debug("Registering Flow for Device ", log.Fields{"flow": flowFromCore},
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700250 log.Fields{"device": f.deviceHandler.deviceID})
Gamze Abakafee36392019-10-03 11:17:24 +0000251 gemPK := gemPortKey{uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId)}
252 flowIDList, ok := f.flowsUsedByGemPort[gemPK]
253 if !ok {
254 flowIDList = []uint32{deviceFlow.FlowId}
255 }
256 flowIDList = appendUnique(flowIDList, deviceFlow.FlowId)
257 f.flowsUsedByGemPort[gemPK] = flowIDList
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530258 // update the flowids for a gem to the KVstore
259 f.resourceMgr.UpdateFlowIDsForGem(uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400260}
261
salmansiddiqui7ac62132019-08-22 03:58:50 +0000262func (f *OpenOltFlowMgr) divideAndAddFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32,
263 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
264 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) {
Gamze Abakafee36392019-10-03 11:17:24 +0000265 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530266 var gemPorts []uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400267 var TpInst *tp.TechProfile
manikkaraj kbf256be2019-03-25 00:13:48 +0530268
Manikkaraj kb1d51442019-07-23 10:41:02 -0400269 log.Infow("Dividing flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "portNo": portNo,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000270 "classifier": classifierInfo, "action": actionInfo, "UsMeterID": UsMeterID, "DsMeterID": DsMeterID, "TpID": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400271 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
272 // is because the flow is an NNI flow and there would be no onu resources associated with it
273 // TODO: properly deal with NNI flows
Manikkaraj kb1d51442019-07-23 10:41:02 -0400274 if onuID <= 0 {
Matt Jeanneret77199612019-07-26 18:08:35 -0400275 log.Errorw("No onu id for flow", log.Fields{"portNo": portNo, "classifer": classifierInfo, "action": actionInfo})
manikkaraj kbf256be2019-03-25 00:13:48 +0530276 return
277 }
278
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530279 uni := getUniPortPath(intfID, int32(onuID), int32(uniID))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400280 log.Debugw("Uni port name", log.Fields{"uni": uni})
Girish Gowdra3d633032019-12-10 16:37:05 +0530281
282 tpLockMapKey := tpLockKey{intfID, onuID, uniID}
283 if f.perUserFlowHandleLock.TryLock(tpLockMapKey) {
284 allocID, gemPorts, TpInst = f.createTcontGemports(intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
285 if allocID == 0 || gemPorts == nil || TpInst == nil {
286 log.Error("alloc-id-gem-ports-tp-unavailable")
287 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
288 return
289 }
290 args := make(map[string]uint32)
291 args[IntfID] = intfID
292 args[OnuID] = onuID
293 args[UniID] = uniID
294 args[PortNo] = portNo
295 args[AllocID] = allocID
296
297 /* Flows can be added specific to gemport if p-bits are received.
298 * If no pbit mentioned then adding flows for all gemports
299 */
300 f.checkAndAddFlow(args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
301 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
302 } else {
303 log.Errorw("failed to acquire per user flow handle lock",
304 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400305 return
306 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530307}
308
salmansiddiqui7ac62132019-08-22 03:58:50 +0000309// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
Gamze Abakafee36392019-10-03 11:17:24 +0000310func (f *OpenOltFlowMgr) CreateSchedulerQueues(sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400311
Gamze Abakafee36392019-10-03 11:17:24 +0000312 log.Debugw("CreateSchedulerQueues", log.Fields{"Dir": sq.direction, "IntfID": sq.intfID,
313 "OnuID": sq.onuID, "UniID": sq.uniID, "TpID": sq.tpID, "MeterID": sq.meterID,
314 "TpInst": sq.tpInst, "flowMetadata": sq.flowMetadata})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400315
Gamze Abakafee36392019-10-03 11:17:24 +0000316 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000317 if err != nil {
318 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400319 }
320
321 /* Lets make a simple assumption that if the meter-id is present on the KV store,
322 * then the scheduler and queues configuration is applied on the OLT device
323 * in the given direction.
324 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000325
Manikkaraj kb1d51442019-07-23 10:41:02 -0400326 var SchedCfg *tp_pb.SchedulerConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000327 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400328 if err != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000329 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 -0400330 return err
331 }
332 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000333 if KvStoreMeter.MeterId == sq.meterID {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400334 log.Debug("Scheduler already created for upstream")
335 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400336 }
Gamze Abakafee36392019-10-03 11:17:24 +0000337 log.Errorw("Dynamic meter update not supported", log.Fields{"KvStoreMeterId": KvStoreMeter.MeterId, "MeterID-in-flow": sq.meterID})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000338 return errors.New("invalid-meter-id-in-flow")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400339 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000340
Gamze Abakafee36392019-10-03 11:17:24 +0000341 log.Debugw("Meter-does-not-exist-Creating-new", log.Fields{"MeterID": sq.meterID, "Direction": Direction})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000342
Gamze Abakafee36392019-10-03 11:17:24 +0000343 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000344 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Gamze Abakafee36392019-10-03 11:17:24 +0000345 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000346 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400347 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000348
349 if err != nil {
350 log.Errorw("Unable to get Scheduler config", log.Fields{"IntfID": sq.intfID, "Direction": sq.direction, "Error": err})
351 return err
352 }
353
Manikkaraj kb1d51442019-07-23 10:41:02 -0400354 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000355 if sq.flowMetadata != nil {
356 for _, meter := range sq.flowMetadata.Meters {
357 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400358 meterConfig = meter
359 log.Debugw("Found-meter-config-from-flowmetadata", log.Fields{"meterConfig": meterConfig})
360 break
361 }
362 }
363 } else {
364 log.Error("Flow-metadata-is-not-present-in-flow")
365 }
366 if meterConfig == nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000367 log.Errorw("Could-not-get-meterbands-from-flowMetadata", log.Fields{"flowMetadata": sq.flowMetadata,
368 "MeterID": sq.meterID})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000369 return errors.New("failed-to-get-meter-from-flowMetadata")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400370 } else if len(meterConfig.Bands) < MaxMeterBand {
Gamze Abakafee36392019-10-03 11:17:24 +0000371 log.Errorw("Invalid-number-of-bands-in-meter", log.Fields{"Bands": meterConfig.Bands, "MeterID": sq.meterID})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000372 return errors.New("invalid-number-of-bands-in-meter")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400373 }
374 cir := meterConfig.Bands[0].Rate
375 cbs := meterConfig.Bands[0].BurstSize
376 eir := meterConfig.Bands[1].Rate
377 ebs := meterConfig.Bands[1].BurstSize
378 pir := cir + eir
379 pbs := cbs + ebs
380 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
381
Gamze Abakafee36392019-10-03 11:17:24 +0000382 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Manikkaraj kb1d51442019-07-23 10:41:02 -0400383
Girish Kumar8f73fe02019-12-09 13:19:37 +0000384 if err := f.pushSchedulerQueuesToDevice(sq, TrafficShaping, TrafficSched); err != nil {
385 log.Errorw("Failed to push traffic scheduler and queues to device", log.Fields{"intfID": sq.intfID, "direction": sq.direction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400386 return err
387 }
388
salmansiddiqui7ac62132019-08-22 03:58:50 +0000389 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400390 * store the meter id on the KV store, for further reference.
391 */
Gamze Abakafee36392019-10-03 11:17:24 +0000392 if err := f.resourceMgr.UpdateMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterConfig); err != nil {
393 log.Error("Failed to update meter id for onu %d, meterid %d", sq.onuID, sq.meterID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400394 return err
395 }
396 log.Debugw("updated-meter-info into KV store successfully", log.Fields{"Direction": Direction,
397 "Meter": meterConfig})
398 return nil
399}
400
Girish Kumar8f73fe02019-12-09 13:19:37 +0000401func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(sq schedQueue, TrafficShaping *tp_pb.TrafficShapingInfo, TrafficSched []*tp_pb.TrafficScheduler) error {
402
403 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
404
405 if err != nil {
406 log.Errorw("Unable to construct traffic queue configuration", log.Fields{"intfID": sq.intfID, "direction": sq.direction})
407 return err
408 }
409
410 log.Debugw("Sending Traffic scheduler create to device", log.Fields{"Direction": sq.direction, "TrafficScheds": TrafficSched})
411 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
412 IntfId: sq.intfID, OnuId: sq.onuID,
413 UniId: sq.uniID, PortNo: sq.uniPort,
414 TrafficScheds: TrafficSched}); err != nil {
415 log.Errorw("Failed to create traffic schedulers", log.Fields{"error": err})
416 return err
417 }
418
419 // On receiving the CreateTrafficQueues request, the driver should create corresponding
420 // downstream queues.
421 log.Debugw("Sending Traffic Queues create to device", log.Fields{"Direction": sq.direction, "TrafficQueues": trafficQueues})
422 if _, err := f.deviceHandler.Client.CreateTrafficQueues(context.Background(),
423 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
424 UniId: sq.uniID, PortNo: sq.uniPort,
425 TrafficQueues: trafficQueues}); err != nil {
426 log.Errorw("Failed to create traffic queues in device", log.Fields{"error": err})
427 return err
428 }
429
430 return nil
431}
432
salmansiddiqui7ac62132019-08-22 03:58:50 +0000433// 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 +0000434func (f *OpenOltFlowMgr) RemoveSchedulerQueues(sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400435
436 var Direction string
437 var SchedCfg *tp_pb.SchedulerConfig
438 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000439 log.Debugw("Removing schedulers and Queues in OLT", log.Fields{"Direction": sq.direction, "IntfID": sq.intfID,
440 "OnuID": sq.onuID, "UniID": sq.uniID, "UniPort": sq.uniPort})
441 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000442 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400443 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000444 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Kumar8f73fe02019-12-09 13:19:37 +0000445 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(sq.tpInst)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400446 Direction = "downstream"
447 }
448
Girish Kumar8f73fe02019-12-09 13:19:37 +0000449 if err != nil {
450 log.Errorw("Unable to get Scheduler config", log.Fields{"IntID": sq.intfID, "Direction": sq.direction, "Error": err})
451 return err
452 }
453
Gamze Abakafee36392019-10-03 11:17:24 +0000454 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400455 if err != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000456 log.Errorf("Failed to get Meter for Onu %d", sq.onuID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400457 return err
458 }
459 if KVStoreMeter == nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000460 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 -0400461 return nil
462 }
463 cir := KVStoreMeter.Bands[0].Rate
464 cbs := KVStoreMeter.Bands[0].BurstSize
465 eir := KVStoreMeter.Bands[1].Rate
466 ebs := KVStoreMeter.Bands[1].BurstSize
467 pir := cir + eir
468 pbs := cbs + ebs
469
470 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
471
Gamze Abakafee36392019-10-03 11:17:24 +0000472 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst, SchedCfg, TrafficShaping)}
Girish Kumar8f73fe02019-12-09 13:19:37 +0000473
474 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(sq.tpInst, sq.direction)
475 if err != nil {
476 log.Errorw("Unable to construct traffic queue configuration", log.Fields{"intfID": sq.intfID, "direction": sq.direction})
477 return err
478 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400479
480 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(context.Background(),
Gamze Abakafee36392019-10-03 11:17:24 +0000481 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
482 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400483 TrafficQueues: TrafficQueues}); err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000484 log.Errorw("Failed to remove traffic queues", log.Fields{"error": err})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400485 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400486 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000487 log.Debug("Removed traffic queues successfully")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400488 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(context.Background(), &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000489 IntfId: sq.intfID, OnuId: sq.onuID,
490 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400491 TrafficScheds: TrafficSched}); err != nil {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000492 log.Errorw("failed to remove traffic schedulers", log.Fields{"error": err})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400493 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400494 }
495
salmansiddiqui7ac62132019-08-22 03:58:50 +0000496 log.Debug("Removed traffic schedulers successfully")
497
498 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400499 * delete the meter id on the KV store.
500 */
Gamze Abakafee36392019-10-03 11:17:24 +0000501 err = f.resourceMgr.RemoveMeterIDForOnu(Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400502 if err != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000503 log.Errorf("Failed to remove meter for onu %d, meter id %d", sq.onuID, KVStoreMeter.MeterId)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000504 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400505 }
506 log.Debugw("Removed-meter-from-KV-store successfully", log.Fields{"MeterId": KVStoreMeter.MeterId, "dir": Direction})
507 return err
508}
509
Gamze Abakafee36392019-10-03 11:17:24 +0000510// This function allocates tconts and GEM ports for an ONU
511func (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) {
512 var allocIDs []uint32
513 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530514 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530515 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000516 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000517
518 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(intfID, onuID, uniID)
519 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400520
521 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530522
523 log.Infow("creating-new-tcont-and-gem", log.Fields{"pon": intfID, "onu": onuID, "uni": uniID})
524
Manikkaraj kb1d51442019-07-23 10:41:02 -0400525 // Check tech profile instance already exists for derived port name
Girish Gowdra54934262019-11-13 14:19:55 +0530526 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000527 if techProfileInstance == nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530528 log.Infow("tp-instance-not-found--creating-new", log.Fields{"path": tpPath})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000529 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(TpID, uni, intfID)
530 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530531 // This should not happen, something wrong in KV backend transaction
Girish Kumar8f73fe02019-12-09 13:19:37 +0000532 log.Errorw("tp-instance-create-failed", log.Fields{"error": err, "tpID": TpID})
Gamze Abakafee36392019-10-03 11:17:24 +0000533 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530534 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000535 f.resourceMgr.UpdateTechProfileIDForOnu(intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530536 } else {
537 log.Debugw("Tech-profile-instance-already-exist-for-given port-name", log.Fields{"uni": uni})
Girish Gowdra3d633032019-12-10 16:37:05 +0530538 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530539 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400540 if UsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000541 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
542 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
543 if err := f.CreateSchedulerQueues(sq); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400544 log.Errorw("CreateSchedulerQueues Failed-upstream", log.Fields{"error": err, "meterID": UsMeterID})
Gamze Abakafee36392019-10-03 11:17:24 +0000545 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400546 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530547 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400548 if DsMeterID != 0 {
Gamze Abakafee36392019-10-03 11:17:24 +0000549 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
550 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
551 if err := f.CreateSchedulerQueues(sq); err != nil {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400552 log.Errorw("CreateSchedulerQueues Failed-downstream", log.Fields{"error": err, "meterID": DsMeterID})
Gamze Abakafee36392019-10-03 11:17:24 +0000553 return 0, nil, nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400554 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530555 }
Gamze Abakafee36392019-10-03 11:17:24 +0000556
557 allocID := techProfileInstance.UsScheduler.AllocID
Gamze Abakafee36392019-10-03 11:17:24 +0000558 for _, gem := range techProfileInstance.UpstreamGemPortAttributeList {
Gamze Abakafee36392019-10-03 11:17:24 +0000559 gemPortIDs = append(gemPortIDs, gem.GemportID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400560 }
Gamze Abakafee36392019-10-03 11:17:24 +0000561
Girish Gowdra3d633032019-12-10 16:37:05 +0530562 if tpInstanceExists {
563 return allocID, gemPortIDs, techProfileInstance
564 }
565
566 allocIDs = appendUnique(allocIDs, allocID)
567 for _, gemPortID := range gemPortIDs {
568 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
569 }
570
Gamze Abakafee36392019-10-03 11:17:24 +0000571 log.Debugw("Allocated Tcont and GEM ports", log.Fields{"allocIDs": allocIDs, "gemports": allgemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530572 // Send Tconts and GEM ports to KV store
Gamze Abakafee36392019-10-03 11:17:24 +0000573 f.storeTcontsGEMPortsIntoKVStore(intfID, onuID, uniID, allocIDs, allgemPortIDs)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000574 return allocID, gemPortIDs, techProfileInstance
manikkaraj kbf256be2019-03-25 00:13:48 +0530575}
576
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700577func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530578
579 log.Debugw("Storing allocated Tconts and GEM ports into KV store",
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700580 log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "allocID": allocID, "gemPortIDs": gemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530581 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700582 if err := f.resourceMgr.UpdateAllocIdsForOnu(intfID, onuID, uniID, allocID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530583 log.Error("Errow while uploading allocID to KV store")
584 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700585 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(intfID, onuID, uniID, gemPortIDs); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530586 log.Error("Errow while uploading GEMports to KV store")
587 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700588 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(gemPortIDs, intfID, onuID, uniID); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530589 log.Error("Errow while uploading gemtopon map to KV store")
590 }
591 log.Debug("Stored tconts and GEM into KV store successfully")
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400592 for _, gemPort := range gemPortIDs {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700593 f.addGemPortToOnuInfoMap(intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400594 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530595}
596
597func (f *OpenOltFlowMgr) populateTechProfilePerPonPort() error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000598 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530599 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000600 for _, intfID := range techRange.IntfIds {
601 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400602 tpCount++
salmansiddiqui7ac62132019-08-22 03:58:50 +0000603 log.Debugw("Init tech profile done", log.Fields{"intfID": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530604 }
605 }
606 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400607 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530608 log.Errorw("Error while populating techprofile",
Manikkaraj kb1d51442019-07-23 10:41:02 -0400609 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000610 return errors.New("error while populating techprofile mgrs")
manikkaraj kbf256be2019-03-25 00:13:48 +0530611 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400612 log.Infow("Populated techprofile for ponports successfully",
613 log.Fields{"numofTech": tpCount, "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts()})
manikkaraj kbf256be2019-03-25 00:13:48 +0530614 return nil
615}
616
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700617func (f *OpenOltFlowMgr) addUpstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530618 portNo uint32, uplinkClassifier map[string]interface{},
619 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700620 allocID uint32, gemportID uint32) {
621 uplinkClassifier[PacketTagType] = SingleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530622 log.Debugw("Adding upstream data flow", log.Fields{"uplinkClassifier": uplinkClassifier, "uplinkAction": uplinkAction})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700623 f.addHSIAFlow(intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700624 Upstream, logicalFlow, allocID, gemportID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530625 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530626}
627
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700628func (f *OpenOltFlowMgr) addDownstreamDataFlow(intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530629 portNo uint32, downlinkClassifier map[string]interface{},
630 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700631 allocID uint32, gemportID uint32) {
632 downlinkClassifier[PacketTagType] = DoubleTag
Manikkaraj k884c1242019-04-11 16:26:42 +0530633 log.Debugw("Adding downstream data flow", log.Fields{"downlinkClassifier": downlinkClassifier,
634 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400635 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
636 if vlan, exists := downlinkClassifier[VlanVid]; exists {
637 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700638 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Manikkaraj kb1d51442019-07-23 10:41:02 -0400639 if uint32(metadata.(uint64)) == MkUniPortNum(intfID, onuID, uniID) {
640 log.Infow("Ignoring DL trap device flow from core", log.Fields{"flow": logicalFlow})
641 return
642 }
643 }
644 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530645 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400646
Manikkaraj k884c1242019-04-11 16:26:42 +0530647 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700648 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400649 // vlan_vid is a uint32. must be type asserted as such or conversion fails
650 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530651 if ok {
652 downlinkAction[VlanVid] = dlClVid & 0xfff
653 } else {
654 log.Error("dl-classifier-vid-type-conversion-failed")
655 return
656 }
657
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700658 f.addHSIAFlow(intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700659 Downstream, logicalFlow, allocID, gemportID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530660}
661
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700662func (f *OpenOltFlowMgr) addHSIAFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +0530663 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700664 allocID uint32, gemPortID uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530665 var networkIntfID uint32
Manikkaraj k884c1242019-04-11 16:26:42 +0530666 /* One of the OLT platform (Broadcom BAL) requires that symmetric
667 flows require the same flow_id to be used across UL and DL.
668 Since HSIA flow is the only symmetric flow currently, we need to
669 re-use the flow_id across both direction. The 'flow_category'
670 takes priority over flow_cookie to find any available HSIA_FLOW
671 id for the ONU.
672 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700673 log.Debugw("Adding HSIA flow", log.Fields{"intfId": intfID, "onuId": onuID, "uniId": uniID, "classifier": classifier,
674 "action": action, "direction": direction, "allocId": allocID, "gemPortId": gemPortID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530675 "logicalFlow": *logicalFlow})
Gamze Abakafee36392019-10-03 11:17:24 +0000676 var vlanPbit uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400677 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000678 vlanPbit = classifier[VlanPcp].(uint32)
679 log.Debugw("Found pbit in the flow", log.Fields{"VlanPbit": vlanPbit})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400680 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700681 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Girish Gowdra3d633032019-12-10 16:37:05 +0530682 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
683 log.Debug("Flow-exists--not-re-adding")
684 return
685 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530686 flowID, err := f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530687 if err != nil {
688 log.Errorw("Flow id unavailable for HSIA flow", log.Fields{"direction": direction})
689 return
690 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700691 var classifierProto *openoltpb2.Classifier
692 var actionProto *openoltpb2.Action
Manikkaraj k884c1242019-04-11 16:26:42 +0530693 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
694 log.Error("Error in making classifier protobuf for hsia flow")
695 return
696 }
697 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
698 if actionProto = makeOpenOltActionField(action); actionProto == nil {
699 log.Errorw("Error in making action protobuf for hsia flow", log.Fields{"direction": direction})
700 return
701 }
702 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530703 networkIntfID, err = getNniIntfID(classifier, action)
704 if err != nil {
705 log.Error("Failed to get nniIntf ID")
706 return
707 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700708 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
709 OnuId: int32(onuID),
710 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +0000711 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +0530712 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700713 AllocId: int32(allocID),
714 NetworkIntfId: int32(networkIntfID),
715 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +0530716 Classifier: classifierProto,
717 Action: actionProto,
718 Priority: int32(logicalFlow.Priority),
719 Cookie: logicalFlow.Cookie,
720 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400721 if ok := f.addFlowToDevice(logicalFlow, &flow); ok {
Manikkaraj k884c1242019-04-11 16:26:42 +0530722 log.Debug("HSIA flow added to device successfully", log.Fields{"direction": direction})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530723 flowsToKVStore := f.getUpdatedFlowInfo(&flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
Manikkaraj k884c1242019-04-11 16:26:42 +0530724 if err := f.updateFlowInfoToKVStore(flow.AccessIntfId,
725 flow.OnuId,
726 flow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400727 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Manikkaraj k884c1242019-04-11 16:26:42 +0530728 log.Errorw("Error uploading HSIA flow into KV store", log.Fields{"flow": flow, "direction": direction, "error": err})
729 return
730 }
731 }
732}
Esin Karamanae41e2b2019-12-17 18:13:13 +0000733
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700734func (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 +0530735
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700736 var dhcpFlow openoltpb2.Flow
737 var actionProto *openoltpb2.Action
738 var classifierProto *openoltpb2.Classifier
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530739 var flowID uint32
740 networkIntfID, err := getNniIntfID(classifier, action)
741 if err != nil {
742 log.Error("Failed to get nniIntf ID")
743 return
744 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530745
746 // Clear the action map
747 for k := range action {
748 delete(action, k)
749 }
750
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700751 action[TrapToHost] = true
752 classifier[UDPSrc] = uint32(68)
753 classifier[UDPDst] = uint32(67)
754 classifier[PacketTagType] = SingleTag
755 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530756
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700757 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
Girish Gowdra3d633032019-12-10 16:37:05 +0530758 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
759 log.Debug("Flow-exists--not-re-adding")
760 return
761 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530762
Girish Gowdra3d633032019-12-10 16:37:05 +0530763 flowID, err = f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, DhcpFlow, 0 /*classifier[VLAN_PCP].(uint32)*/)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530764
765 if err != nil {
Girish Gowdra3d633032019-12-10 16:37:05 +0530766 log.Errorw("flowId unavailable for UL DHCP", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530767 return
768 }
769
770 log.Debugw("Creating UL DHCP flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID})
771
772 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
773 log.Error("Error in making classifier protobuf for ul flow")
774 return
775 }
776 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
777 if actionProto = makeOpenOltActionField(action); actionProto == nil {
778 log.Error("Error in making action protobuf for ul flow")
779 return
780 }
781
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700782 dhcpFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
783 OnuId: int32(onuID),
784 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530785 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700786 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700787 AllocId: int32(allocID),
788 NetworkIntfId: int32(networkIntfID),
789 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530790 Classifier: classifierProto,
791 Action: actionProto,
792 Priority: int32(logicalFlow.Priority),
793 Cookie: logicalFlow.Cookie,
794 PortNo: portNo}
795
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400796 if ok := f.addFlowToDevice(logicalFlow, &dhcpFlow); ok {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530797 log.Debug("DHCP UL flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530798 flowsToKVStore := f.getUpdatedFlowInfo(&dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +0530799 if err := f.updateFlowInfoToKVStore(dhcpFlow.AccessIntfId,
800 dhcpFlow.OnuId,
801 dhcpFlow.UniId,
802 dhcpFlow.FlowId, flowsToKVStore); err != nil {
803 log.Errorw("Error uploading DHCP UL flow into KV store", log.Fields{"flow": dhcpFlow, "error": err})
804 return
805 }
806 }
807
manikkaraj kbf256be2019-03-25 00:13:48 +0530808 return
809}
810
Esin Karamanae41e2b2019-12-17 18:13:13 +0000811//addIGMPTrapFlow creates IGMP trap-to-host flow
812func (f *OpenOltFlowMgr) addIGMPTrapFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
813 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32) {
814 f.addUpstreamTrapFlow(intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, IgmpFlow)
815}
816
817//addUpstreamTrapFlow creates a trap-to-host flow
818func (f *OpenOltFlowMgr) addUpstreamTrapFlow(intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
819 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, flowType string) {
820
821 var flow openoltpb2.Flow
822 var actionProto *openoltpb2.Action
823 var classifierProto *openoltpb2.Classifier
824
825 networkIntfID, err := getNniIntfID(classifier, action)
826 if err != nil {
827 log.Error("Failed to get nniIntf ID")
828 return
829 }
830
831 // Clear the action map
832 for k := range action {
833 delete(action, k)
834 }
835
836 action[TrapToHost] = true
837 classifier[PacketTagType] = SingleTag
838 delete(classifier, VlanVid)
839
840 flowStoreCookie := getFlowStoreCookie(classifier, gemPortID)
841 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkIntfID), int32(onuID), int32(uniID), flowStoreCookie); present {
842 log.Debug("Flow-exists--not-re-adding")
843 return
844 }
845
846 flowID, err := f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, flowType, 0, 0 /*classifier[VLAN_PCP].(uint32)*/)
847
848 if err != nil {
849 log.Errorw("flowId unavailable for upstream trap flow", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie, "flowType": flowType})
850 return
851 }
852
853 log.Debugw("Creating upstream trap flow", log.Fields{"ul_classifier": classifier, "ul_action": action, "uplinkFlowId": flowID, "flowType": flowType})
854
855 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
856 log.Error("Error in making classifier protobuf for ul flow")
857 return
858 }
859 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
860 if actionProto = makeOpenOltActionField(action); actionProto == nil {
861 log.Error("Error in making action protobuf for ul flow")
862 return
863 }
864
865 flow = openoltpb2.Flow{AccessIntfId: int32(intfID),
866 OnuId: int32(onuID),
867 UniId: int32(uniID),
868 FlowId: flowID,
869 FlowType: Upstream,
870 AllocId: int32(allocID),
871 NetworkIntfId: int32(networkIntfID),
872 GemportId: int32(gemPortID),
873 Classifier: classifierProto,
874 Action: actionProto,
875 Priority: int32(logicalFlow.Priority),
876 Cookie: logicalFlow.Cookie,
877 PortNo: portNo}
878
879 if ok := f.addFlowToDevice(logicalFlow, &flow); ok {
880 log.Debugf("%s UL flow added to device successfully", flowType)
881
882 flowsToKVStore := f.getUpdatedFlowInfo(&flow, flowStoreCookie, flowType, flowID, logicalFlow.Id)
883 if err := f.updateFlowInfoToKVStore(flow.AccessIntfId,
884 flow.OnuId,
885 flow.UniId,
886 flow.FlowId, flowsToKVStore); err != nil {
887 log.Errorw("Error uploading UL flow into KV store", log.Fields{"flow": flow, "error": err})
888 return
889 }
890 }
891
892 return
893}
894
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700895// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530896func (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 -0700897 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 +0530898
899 uplinkClassifier := make(map[string]interface{})
900 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +0530901
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700902 var upstreamFlow openoltpb2.Flow
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530903 var networkIntfID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530904
905 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700906 uplinkClassifier[EthType] = uint32(EapEthType)
907 uplinkClassifier[PacketTagType] = SingleTag
908 uplinkClassifier[VlanVid] = vlanID
manikkaraj kbf256be2019-03-25 00:13:48 +0530909 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700910 uplinkAction[TrapToHost] = true
911 flowStoreCookie := getFlowStoreCookie(uplinkClassifier, gemPortID)
Girish Gowdra3d633032019-12-10 16:37:05 +0530912 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
913 log.Debug("Flow-exists--not-re-adding")
914 return
915 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530916 //Add Uplink EAPOL Flow
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530917 uplinkFlowID, err := f.resourceMgr.GetFlowID(intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0)
manikkaraj kbf256be2019-03-25 00:13:48 +0530918 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700919 log.Errorw("flowId unavailable for UL EAPOL", log.Fields{"intfId": intfID, "onuId": onuID, "flowStoreCookie": flowStoreCookie})
Manikkaraj k884c1242019-04-11 16:26:42 +0530920 return
manikkaraj kbf256be2019-03-25 00:13:48 +0530921 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700922 var classifierProto *openoltpb2.Classifier
923 var actionProto *openoltpb2.Action
924 log.Debugw("Creating UL EAPOL flow", log.Fields{"ul_classifier": uplinkClassifier, "ul_action": uplinkAction, "uplinkFlowId": uplinkFlowID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530925
926 if classifierProto = makeOpenOltClassifierField(uplinkClassifier); classifierProto == nil {
927 log.Error("Error in making classifier protobuf for ul flow")
928 return
929 }
930 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
931 if actionProto = makeOpenOltActionField(uplinkAction); actionProto == nil {
932 log.Error("Error in making action protobuf for ul flow")
933 return
934 }
935 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530936 networkIntfID, err = getNniIntfID(classifier, action)
937 if err != nil {
938 log.Error("Failed to get nniIntf ID")
939 return
940 }
941
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700942 upstreamFlow = openoltpb2.Flow{AccessIntfId: int32(intfID),
943 OnuId: int32(onuID),
944 UniId: int32(uniID),
945 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -0700946 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700947 AllocId: int32(allocID),
948 NetworkIntfId: int32(networkIntfID),
949 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +0530950 Classifier: classifierProto,
951 Action: actionProto,
952 Priority: int32(logicalFlow.Priority),
953 Cookie: logicalFlow.Cookie,
954 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400955 if ok := f.addFlowToDevice(logicalFlow, &upstreamFlow); ok {
manikkaraj kbf256be2019-03-25 00:13:48 +0530956 log.Debug("EAPOL UL flow added to device successfully")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400957 flowCategory := "EAPOL"
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530958 flowsToKVStore := f.getUpdatedFlowInfo(&upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
manikkaraj kbf256be2019-03-25 00:13:48 +0530959 if err := f.updateFlowInfoToKVStore(upstreamFlow.AccessIntfId,
960 upstreamFlow.OnuId,
961 upstreamFlow.UniId,
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400962 upstreamFlow.FlowId,
963 /* lowCategory, */
964 flowsToKVStore); err != nil {
manikkaraj kbf256be2019-03-25 00:13:48 +0530965 log.Errorw("Error uploading EAPOL UL flow into KV store", log.Fields{"flow": upstreamFlow, "error": err})
966 return
967 }
968 }
Girish Gowdra3d633032019-12-10 16:37:05 +0530969
manikkaraj kbf256be2019-03-25 00:13:48 +0530970 log.Debugw("Added EAPOL flows to device successfully", log.Fields{"flow": logicalFlow})
971}
972
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700973func makeOpenOltClassifierField(classifierInfo map[string]interface{}) *openoltpb2.Classifier {
974 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -0700975
976 classifier.EthType, _ = classifierInfo[EthType].(uint32)
977 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
978 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
979 vid := vlanID & VlanvIDMask
980 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -0400981 classifier.OVid = vid
982 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530983 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700984 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
985 vid := uint32(metadata)
986 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -0400987 classifier.IVid = vid
988 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530989 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700990 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400991 if vlanPcp == 0 {
992 classifier.OPbits = VlanPCPMask
993 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700994 classifier.OPbits = vlanPcp & VlanPCPMask
Manikkaraj kb1d51442019-07-23 10:41:02 -0400995 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530996 }
David K. Bainbridge82efc492019-09-04 09:57:11 -0700997 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
998 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
999 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1000 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
1001 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1002 classifier.PktTagType = pktTagType
1003
1004 switch pktTagType {
1005 case SingleTag:
1006 case DoubleTag:
1007 case Untagged:
1008 default:
manikkaraj kbf256be2019-03-25 00:13:48 +05301009 log.Error("Invalid tag type in classifier") // should not hit
1010 return nil
1011 }
1012 }
1013 return &classifier
1014}
1015
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001016func makeOpenOltActionField(actionInfo map[string]interface{}) *openoltpb2.Action {
1017 var actionCmd openoltpb2.ActionCmd
1018 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301019 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001020 if _, ok := actionInfo[PopVlan]; ok {
1021 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301022 action.Cmd.RemoveOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001023 } else if _, ok := actionInfo[PushVlan]; ok {
1024 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301025 action.Cmd.AddOuterTag = true
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001026 } else if _, ok := actionInfo[TrapToHost]; ok {
1027 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301028 } else {
1029 log.Errorw("Invalid-action-field", log.Fields{"action": actionInfo})
1030 return nil
1031 }
1032 return &action
1033}
1034
Manikkaraj kb1d51442019-07-23 10:41:02 -04001035func (f *OpenOltFlowMgr) getTPpath(intfID uint32, uni string, TpID uint32) string {
1036 return f.techprofile[intfID].GetTechProfileInstanceKVPath(TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +05301037}
1038
Gamze Abakafee36392019-10-03 11:17:24 +00001039// DeleteTechProfileInstances removes the tech profile instances from persistent storage
1040func (f *OpenOltFlowMgr) DeleteTechProfileInstances(intfID uint32, onuID uint32, uniID uint32, sn string) error {
1041 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(intfID, onuID, uniID)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001042 uniPortName := fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001043 for _, tpID := range tpIDList {
1044 if err := f.DeleteTechProfileInstance(intfID, onuID, uniID, uniPortName, tpID); err != nil {
1045 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 +05301046 // return err
1047 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001048 }
1049 }
1050 return nil
1051}
1052
1053// DeleteTechProfileInstance removes the tech profile instance from persistent storage
1054func (f *OpenOltFlowMgr) DeleteTechProfileInstance(intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
1055 if uniPortName == "" {
1056 uniPortName = fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1057 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001058 if err := f.techprofile[intfID].DeleteTechProfileInstance(tpID, uniPortName); err != nil {
1059 log.Debugw("Failed-to-delete-tp-instance-from-kv-store", log.Fields{"tp-id": tpID, "uni-port-name": uniPortName})
1060 return err
1061 }
1062 return nil
1063}
1064
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001065func getFlowStoreCookie(classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +05301066 if len(classifier) == 0 { // should never happen
1067 log.Error("Invalid classfier object")
1068 return 0
1069 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301070 log.Debugw("generating flow store cookie", log.Fields{"classifier": classifier, "gemPortID": gemPortID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301071 var jsonData []byte
1072 var flowString string
1073 var err error
1074 // TODO: Do we need to marshall ??
1075 if jsonData, err = json.Marshal(classifier); err != nil {
1076 log.Error("Failed to encode classifier")
1077 return 0
1078 }
1079 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001080 if gemPortID != 0 {
1081 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +05301082 }
1083 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001084 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +05301085 hash := big.NewInt(0)
1086 hash.SetBytes(h.Sum(nil))
Girish Gowdra3d633032019-12-10 16:37:05 +05301087 generatedHash := hash.Uint64()
1088 log.Debugw("hash generated", log.Fields{"hash": generatedHash})
1089 return generatedHash
manikkaraj kbf256be2019-03-25 00:13:48 +05301090}
1091
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301092func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openoltpb2.Flow, flowStoreCookie uint64, flowCategory string, deviceFlowID uint32, logicalFlowID uint64) *[]rsrcMgr.FlowInfo {
1093 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001094 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001095 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1096 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1097 */
1098 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001099 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001100 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001101 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001102 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001103 // Get existing flows matching flowid for given subscriber from KV store
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301104 existingFlows := f.resourceMgr.GetFlowIDInfo(intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001105 if existingFlows != nil {
1106 log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001107 //for _, f := range *existingFlows {
1108 // flows = append(flows, f)
1109 //}
1110 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001111 }
1112 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 +05301113 return &flows
1114}
1115
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001116//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
1117// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
1118// var intfId uint32
1119// /* For flows which trap out of the NNI, the AccessIntfId is invalid
1120// (set to -1). In such cases, we need to refer to the NetworkIntfId .
1121// */
1122// if flow.AccessIntfId != -1 {
1123// intfId = uint32(flow.AccessIntfId)
1124// } else {
1125// intfId = uint32(flow.NetworkIntfId)
1126// }
1127// // Get existing flows matching flowid for given subscriber from KV store
1128// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
1129// if existingFlows != nil {
1130// log.Debugw("Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
1131// for _, f := range *existingFlows {
1132// flows = append(flows, f)
1133// }
1134// }
1135// log.Debugw("Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
1136// return &flows
1137//}
1138
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001139func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
manikkaraj k17652a72019-05-06 09:06:36 -04001140 log.Debugw("Storing flow(s) into KV store", log.Fields{"flows": *flows})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001141 if err := f.resourceMgr.UpdateFlowIDInfo(intfID, onuID, uniID, flowID, flows); err != nil {
manikkaraj k17652a72019-05-06 09:06:36 -04001142 log.Debug("Error while Storing flow into KV store")
1143 return err
1144 }
1145 log.Info("Stored flow(s) into KV store successfully!")
manikkaraj kbf256be2019-03-25 00:13:48 +05301146 return nil
1147}
1148
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001149func (f *OpenOltFlowMgr) addFlowToDevice(logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) bool {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001150
1151 var intfID uint32
1152 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1153 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1154 */
1155 if deviceFlow.AccessIntfId != -1 {
1156 intfID = uint32(deviceFlow.AccessIntfId)
1157 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001158 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001159 intfID = uint32(deviceFlow.NetworkIntfId)
1160 }
1161
manikkaraj kbf256be2019-03-25 00:13:48 +05301162 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1163 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001164
1165 st, _ := status.FromError(err)
1166 if st.Code() == codes.AlreadyExists {
Gamze Abakafee36392019-10-03 11:17:24 +00001167 log.Debug("Flow already exists", log.Fields{"err": err, "deviceFlow": deviceFlow})
Girish Gowdra3d633032019-12-10 16:37:05 +05301168 return true
manikkaraj kbf256be2019-03-25 00:13:48 +05301169 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001170
1171 if err != nil {
1172 log.Errorw("Failed to Add flow to device", log.Fields{"err": err, "deviceFlow": deviceFlow})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001173 f.resourceMgr.FreeFlowID(intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001174 return false
1175 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301176 if deviceFlow.GemportId != -1 {
1177 // No need to register the flow if it is a trap on nni flow.
1178 f.registerFlow(logicalFlow, deviceFlow)
1179 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301180 log.Debugw("Flow added to device successfully ", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001181 return true
1182}
1183
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001184func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) bool {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001185 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1186 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1187 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001188 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
1189 log.Warnw("Can not remove flow from device since it's unreachable", log.Fields{"err": err, "deviceFlow": deviceFlow})
1190 //Assume the flow is removed
1191 return true
1192 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001193 log.Errorw("Failed to Remove flow from device", log.Fields{"err": err, "deviceFlow": deviceFlow})
1194 return false
serkant.uluderya245caba2019-09-24 23:15:29 -07001195
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001196 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001197 log.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301198 return true
1199}
1200
1201/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1202 //update core flows_proxy : flows_proxy.update('/', flows)
1203}
1204
1205func generateStoredId(flowId uint32, direction string)uint32{
1206
David K. Bainbridge82efc492019-09-04 09:57:11 -07001207 if direction == Upstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301208 log.Debug("Upstream flow shifting flowid")
1209 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001210 }else if direction == Downstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301211 log.Debug("Downstream flow not shifting flowid")
1212 return flowId
1213 }else{
1214 log.Errorw("Unrecognized direction",log.Fields{"direction": direction})
1215 return flowId
1216 }
1217}
1218
1219*/
1220
Humera Kouser94d7a842019-08-25 19:04:32 -04001221func (f *OpenOltFlowMgr) addLLDPFlow(flow *ofp.OfpFlowStats, portNo uint32) {
1222
1223 classifierInfo := make(map[string]interface{})
1224 actionInfo := make(map[string]interface{})
1225
1226 classifierInfo[EthType] = uint32(LldpEthType)
1227 classifierInfo[PacketTagType] = Untagged
1228 actionInfo[TrapToHost] = true
1229
1230 // LLDP flow is installed to trap LLDP packets on the NNI port.
1231 // We manage flow_id resource pool on per PON port basis.
1232 // Since this situation is tricky, as a hack, we pass the NNI port
1233 // index (network_intf_id) as PON port Index for the flow_id resource
1234 // pool. Also, there is no ONU Id available for trapping LLDP packets
1235 // on NNI port, use onu_id as -1 (invalid)
1236 // ****************** CAVEAT *******************
1237 // This logic works if the NNI Port Id falls within the same valid
1238 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1239 // we need to have a re-look at this.
1240 // *********************************************
1241
1242 var onuID = -1
1243 var uniID = -1
1244 var gemPortID = -1
1245
1246 var networkInterfaceID = IntfIDFromNniPortNum(portNo)
1247 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301248 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Humera Kouser94d7a842019-08-25 19:04:32 -04001249 log.Debug("Flow-exists--not-re-adding")
1250 return
1251 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301252 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001253
1254 if err != nil {
1255 log.Errorw("Flow id unavailable for LLDP traponNNI flow", log.Fields{"error": err})
1256 return
1257 }
1258 var classifierProto *openoltpb2.Classifier
1259 var actionProto *openoltpb2.Action
1260 if classifierProto = makeOpenOltClassifierField(classifierInfo); classifierProto == nil {
1261 log.Error("Error in making classifier protobuf for LLDP trap on nni flow")
1262 return
1263 }
1264 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1265 if actionProto = makeOpenOltActionField(actionInfo); actionProto == nil {
1266 log.Error("Error in making action protobuf for LLDP trap on nni flow")
1267 return
1268 }
1269 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
1270
1271 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1272 OnuId: int32(onuID), // OnuId not required
1273 UniId: int32(uniID), // UniId not used
1274 FlowId: flowID,
1275 FlowType: Downstream,
1276 NetworkIntfId: int32(networkInterfaceID),
1277 GemportId: int32(gemPortID),
1278 Classifier: classifierProto,
1279 Action: actionProto,
1280 Priority: int32(flow.Priority),
1281 Cookie: flow.Cookie,
1282 PortNo: portNo}
1283 if ok := f.addFlowToDevice(flow, &downstreamflow); ok {
1284 log.Debug("LLDP trap on NNI flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301285 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID, flow.Id)
Humera Kouser94d7a842019-08-25 19:04:32 -04001286 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1287 int32(onuID),
1288 int32(uniID),
1289 flowID, flowsToKVStore); err != nil {
1290 log.Errorw("Error uploading LLDP flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1291 }
1292 }
1293 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301294}
1295
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301296func getUniPortPath(intfID uint32, onuID int32, uniID int32) string {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001297 return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1298}
1299
1300//getOnuChildDevice to fetch onu
1301func (f *OpenOltFlowMgr) getOnuChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
1302 log.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
1303 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
1304 onuDevice := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301305 if onuDevice == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001306 log.Errorw("onu not found", log.Fields{"intfId": parentPortNo, "onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301307 return nil, errors.New("onu not found")
manikkaraj kbf256be2019-03-25 00:13:48 +05301308 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301309 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1310 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301311}
1312
1313func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001314 log.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301315 return nil
1316}
1317
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001318func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
1319 log.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301320}
1321
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001322func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001323 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001324 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001325 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001326 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001327}
1328
Girish Gowdra6b130582019-11-20 16:45:20 +05301329func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1330 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
1331 if err != nil {
1332 log.Errorw("error fetching child device from core", log.Fields{"onuId": onuID})
1333 return err
1334 }
1335
1336 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
1337 log.Debugw("sending gem port delete to openonu adapter", log.Fields{"msg": *delGemPortMsg})
1338 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1339 delGemPortMsg,
1340 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
1341 f.deviceHandler.deviceType,
1342 onuDevice.Type,
1343 onuDevice.Id,
1344 onuDevice.ProxyAddress.DeviceId, ""); sendErr != nil {
1345 log.Errorw("failure sending del gem port to onu adapter", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1346 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1347 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1348 return sendErr
1349 }
1350 log.Debugw("success sending del gem port to onu adapter", log.Fields{"msg": delGemPortMsg})
1351 return nil
1352}
1353
1354func (f *OpenOltFlowMgr) sendDeleteTcontToChild(intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1355 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
1356 if err != nil {
1357 log.Errorw("error fetching child device from core", log.Fields{"onuId": onuID})
1358 return err
1359 }
1360
1361 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
1362 log.Debugw("sending tcont delete to openonu adapter", log.Fields{"msg": *delTcontMsg})
1363 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1364 delTcontMsg,
1365 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
1366 f.deviceHandler.deviceType,
1367 onuDevice.Type,
1368 onuDevice.Id,
1369 onuDevice.ProxyAddress.DeviceId, ""); sendErr != nil {
1370 log.Errorw("failure sending del tcont to onu adapter", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1371 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1372 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1373 return sendErr
1374 }
1375 log.Debugw("success sending del tcont to onu adapter", log.Fields{"msg": delTcontMsg})
1376 return nil
1377}
1378
Girish Gowdra3d633032019-12-10 16:37:05 +05301379func (f *OpenOltFlowMgr) deletePendingFlows(Intf uint32, onuID int32, uniID int32) {
1380 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1381 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); ok {
1382 if val.(int) > 0 {
1383 pnFlDels := val.(int) - 1
1384 if pnFlDels > 0 {
1385 log.Debugw("flow delete succeeded, more pending",
1386 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID, "currPendingFlowCnt": pnFlDels})
1387 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1388 } else {
1389 log.Debugw("all pending flow deletes handled, removing entry from map",
1390 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1391 f.pendingFlowDelete.Delete(pnFlDelKey)
1392 }
1393 }
1394 } else {
1395 log.Debugw("no pending delete flows found",
1396 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1397
1398 }
1399
1400}
1401
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301402//clearResources clears pon resources in kv store and the device
1403func (f *OpenOltFlowMgr) clearResources(flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
1404 gemPortID int32, flowID uint32, flowDirection string,
1405 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001406
Chaitrashree G S90a17952019-11-14 21:51:21 -05001407 tpID, err := getTpIDFromFlow(flow)
1408 if err != nil {
1409 log.Error("metadata-is-not-present-invalid-flow-to-process", log.Fields{"pon": Intf, "onuID": onuID, "uniID": uniID})
1410 return err
1411 }
Gamze Abakafee36392019-10-03 11:17:24 +00001412
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001413 if len(updatedFlows) >= 0 {
1414 // There are still flows referencing the same flow_id.
1415 // So the flow should not be freed yet.
1416 // For ex: Case of HSIA where same flow is shared
1417 // between DS and US.
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301418 f.updateFlowInfoToKVStore(int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001419 if len(updatedFlows) == 0 {
Girish Gowdra3d633032019-12-10 16:37:05 +05301420 // Do this for subscriber flows only (not trap from NNI flows)
1421 if onuID != -1 && uniID != -1 {
1422 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1423 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
1424 log.Debugw("creating entry for pending flow delete",
1425 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1426 f.pendingFlowDelete.Store(pnFlDelKey, 1)
1427 } else {
1428 pnFlDels := val.(int) + 1
1429 log.Debugw("updating flow delete entry",
1430 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID, "currPendingFlowCnt": pnFlDels})
1431 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1432 }
1433
1434 defer f.deletePendingFlows(Intf, onuID, uniID)
1435 }
1436
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301437 log.Debugw("Releasing flow Id to resource manager", log.Fields{"Intf": Intf, "onuId": onuID, "uniId": uniID, "flowId": flowID})
1438 f.resourceMgr.FreeFlowID(Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001439
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301440 uni := getUniPortPath(Intf, onuID, uniID)
1441 tpPath := f.getTPpath(Intf, uni, tpID)
Gamze Abakafee36392019-10-03 11:17:24 +00001442 log.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301443 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(tpID, tpPath)
Gamze Abakafee36392019-10-03 11:17:24 +00001444 if err != nil { // This should not happen, something wrong in KV backend transaction
1445 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": 20, "path": tpPath})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301446 return err
Gamze Abakafee36392019-10-03 11:17:24 +00001447 }
1448 if techprofileInst == nil {
1449 log.Errorw("Tech-profile-instance-does-not-exist-in-KV Store", log.Fields{"tpPath": tpPath})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301450 return err
Gamze Abakafee36392019-10-03 11:17:24 +00001451 }
1452
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301453 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00001454 if f.isGemPortUsedByAnotherFlow(gemPK) {
1455 flowIDs := f.flowsUsedByGemPort[gemPK]
1456 for i, flowIDinMap := range flowIDs {
1457 if flowIDinMap == flowID {
1458 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301459 // everytime flowsUsedByGemPort cache is updated the same should be updated
1460 // in kv store by calling UpdateFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001461 f.flowsUsedByGemPort[gemPK] = flowIDs
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301462 f.resourceMgr.UpdateFlowIDsForGem(Intf, uint32(gemPortID), flowIDs)
Gamze Abakafee36392019-10-03 11:17:24 +00001463 break
1464 }
1465 }
1466 log.Debugw("Gem port id is still used by other flows", log.Fields{"gemPortID": gemPortID, "usedByFlows": flowIDs})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301467 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00001468 }
Gamze Abakafee36392019-10-03 11:17:24 +00001469 log.Debugf("Gem port id %d is not used by another flow - releasing the gem port", gemPortID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301470 f.resourceMgr.RemoveGemPortIDForOnu(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001471 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1472 // 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 +05301473 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(uint32(gemPortID), Intf)
Gamze Abakafee36392019-10-03 11:17:24 +00001474 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301475 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1476 // by calling DeleteFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001477 delete(f.flowsUsedByGemPort, gemPK)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301478 f.resourceMgr.DeleteFlowIDsForGem(Intf, uint32(gemPortID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301479 f.resourceMgr.FreeGemPortID(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001480 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05301481 // Delete the gem port on the ONU.
1482 if err := f.sendDeleteGemPortToChild(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
1483 log.Errorw("error processing delete gem-port towards onu",
1484 log.Fields{"err": err, "pon": Intf, "onuID": onuID, "uniID": uniID, "gemPortId": gemPortID})
1485 }
Gamze Abakafee36392019-10-03 11:17:24 +00001486
Girish Gowdra54934262019-11-13 14:19:55 +05301487 ok, _ := f.isTechProfileUsedByAnotherGem(Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001488 if !ok {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301489 f.resourceMgr.RemoveTechProfileIDForOnu(Intf, uint32(onuID), uint32(uniID), tpID)
1490 f.RemoveSchedulerQueues(schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1491 f.RemoveSchedulerQueues(schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1492 f.DeleteTechProfileInstance(Intf, uint32(onuID), uint32(uniID), "", tpID)
1493 f.resourceMgr.FreeAllocID(Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301494 // Delete the TCONT on the ONU.
1495 if err := f.sendDeleteTcontToChild(Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
1496 log.Errorw("error processing delete tcont towards onu",
1497 log.Fields{"pon": Intf, "onuID": onuID, "uniID": uniID, "allocId": techprofileInst.UsScheduler.AllocID})
1498 }
Gamze Abakafee36392019-10-03 11:17:24 +00001499 }
1500 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001501 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301502 return nil
1503}
1504
1505func (f *OpenOltFlowMgr) clearFlowFromResourceManager(flow *ofp.OfpFlowStats, flowDirection string) {
1506
1507 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowDirection": flowDirection, "flow": *flow})
1508 var updatedFlows []rsrcMgr.FlowInfo
1509 var flowID uint32
1510 var onuID, uniID int32
1511 classifierInfo := make(map[string]interface{})
1512
1513 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
1514 if err != nil {
1515 log.Error(err)
1516 return
1517 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301518
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301519 onuID = int32(onu)
1520 uniID = int32(uni)
1521
1522 for _, field := range flows.GetOfbFields(flow) {
1523 if field.Type == flows.IP_PROTO {
1524 classifierInfo[IPProto] = field.GetIpProto()
1525 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
1526 }
1527 }
1528 log.Debugw("Extracted access info from flow to be deleted",
1529 log.Fields{"ponIntf": Intf, "onuID": onuID, "uniID": uniID})
1530
1531 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1532 onuID = -1
1533 uniID = -1
1534 log.Debug("Trap on nni flow set oni, uni to -1")
1535 Intf = IntfIDFromNniPortNum(inPort)
1536 }
1537 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(Intf, onuID, uniID)
1538 for _, flowID = range flowIds {
1539 flowInfo := f.resourceMgr.GetFlowIDInfo(Intf, onuID, uniID, flowID)
1540 if flowInfo == nil {
1541 log.Debugw("No FlowInfo found found in KV store",
1542 log.Fields{"Intf": Intf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1543 return
1544 }
1545 updatedFlows = nil
1546 for _, flow := range *flowInfo {
1547 updatedFlows = append(updatedFlows, flow)
1548 }
1549
1550 for i, storedFlow := range updatedFlows {
1551 if flow.Id == storedFlow.LogicalFlowID {
1552 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
1553 log.Debugw("Flow to be deleted", log.Fields{"flow": storedFlow})
1554 if ok := f.removeFlowFromDevice(&removeFlowMessage); ok {
1555 log.Debug("Flow removed from device successfully")
1556 //Remove the Flow from FlowInfo
1557 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1558 err = f.clearResources(flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
1559 flowID, flowDirection, portNum, updatedFlows)
1560 if err != nil {
1561 log.Error("Failed to clear resources for flow", log.Fields{"flow": storedFlow})
1562 return
1563 }
1564 } else {
1565 log.Error("Failed to remove flow from device")
1566 return
1567 }
1568 }
1569 }
1570 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001571}
1572
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001573//RemoveFlow removes the flow from the device
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001574func (f *OpenOltFlowMgr) RemoveFlow(flow *ofp.OfpFlowStats) {
1575 log.Debugw("Removing Flow", log.Fields{"flow": flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301576 var direction string
1577 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001578
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301579 for _, action := range flows.GetActions(flow) {
1580 if action.Type == flows.OUTPUT {
1581 if out := action.GetOutput(); out != nil {
1582 actionInfo[Output] = out.GetPort()
1583 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
1584 } else {
1585 log.Error("Invalid output port in action")
1586 return
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001587 }
1588 }
1589 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301590 if IsUpstream(actionInfo[Output].(uint32)) {
1591 direction = Upstream
1592 } else {
1593 direction = Downstream
1594 }
1595
1596 f.clearFlowFromResourceManager(flow, direction) //TODO: Take care of the limitations
1597
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001598 return
1599}
1600
Girish Gowdra3d633032019-12-10 16:37:05 +05301601func (f *OpenOltFlowMgr) waitForFlowDeletesToCompleteForOnu(ctx context.Context, intfID uint32, onuID uint32,
1602 uniID uint32, ch chan bool) {
1603 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
1604 for {
1605 select {
1606 case <-time.After(20 * time.Millisecond):
1607 if flowDelRefCnt, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok || flowDelRefCnt == 0 {
1608 log.Debug("pending flow deletes completed")
1609 ch <- true
1610 return
1611 }
1612 case <-ctx.Done():
1613 log.Error("flow delete wait handler routine canceled")
1614 return
1615 }
1616 }
1617}
1618
Esin Karamanae41e2b2019-12-17 18:13:13 +00001619//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
1620func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
1621 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
1622 if ethType, ok := classifierInfo[EthType]; ok {
1623 if ethType.(uint32) == IPv4EthType {
1624 if ipProto, ok := classifierInfo[IPProto]; ok {
1625 if ipProto.(uint32) == IgmpProto {
1626 return true
1627 }
1628 }
1629 }
1630 }
1631 }
1632 return false
1633}
1634
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001635// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05301636// nolint: gocyclo
Manikkaraj kb1d51442019-07-23 10:41:02 -04001637func (f *OpenOltFlowMgr) AddFlow(flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001638 classifierInfo := make(map[string]interface{})
1639 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001640 var UsMeterID uint32
1641 var DsMeterID uint32
1642
1643 log.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001644 formulateClassifierInfoFromFlow(classifierInfo, flow)
1645
1646 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
1647 if err != nil {
1648 // Error logging is already done in the called function
1649 // So just return in case of error
1650 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301651 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001652
manikkaraj k17652a72019-05-06 09:06:36 -04001653 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00001654 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
1655 if err != nil {
1656 // error if any, already logged in the called function
1657 return
manikkaraj k17652a72019-05-06 09:06:36 -04001658 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001659
David K. Bainbridge82efc492019-09-04 09:57:11 -07001660 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[Output]})
1661 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00001662
Humera Kouser94d7a842019-08-25 19:04:32 -04001663 if ethType, ok := classifierInfo[EthType]; ok {
1664 if ethType.(uint32) == LldpEthType {
1665 log.Info("Adding LLDP flow")
1666 f.addLLDPFlow(flow, portNo)
1667 return
1668 }
1669 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001670 if ipProto, ok := classifierInfo[IPProto]; ok {
1671 if ipProto.(uint32) == IPProtoDhcp {
1672 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05301673 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001674 log.Debug("trap-dhcp-from-nni-flow")
1675 f.addDHCPTrapFlowOnNNI(flow, classifierInfo, portNo)
1676 return
1677 }
1678 }
1679 }
1680 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001681 if isIgmpTrapDownstreamFlow(classifierInfo) {
1682 log.Debug("trap-igmp-from-nni-flow")
1683 f.addIgmpTrapFlowOnNNI(flow, classifierInfo, portNo)
1684 return
1685 }
A R Karthick1f85b802019-10-11 05:06:05 +00001686
1687 f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301688 f.resourceMgr.AddUniPortToOnuInfo(intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00001689
Chaitrashree G S90a17952019-11-14 21:51:21 -05001690 TpID, err := getTpIDFromFlow(flow)
1691 if err != nil {
1692 log.Error("metadata-is-not-present-invalid-flow-to-process", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1693 return
1694 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001695 log.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001696 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07001697 UsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001698 log.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
1699 } else {
Scott Baker355d1742019-10-24 10:57:52 -07001700 DsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001701 log.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
1702
1703 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301704
1705 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
1706 if _, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
1707 log.Debugw("no pending flows found, going ahead with flow install", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1708 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
1709 } else {
1710 ctx := context.Background()
1711 ctx, cancel := context.WithCancel(ctx)
1712 defer cancel()
1713 pendingFlowDelComplete := make(chan bool)
1714 go f.waitForFlowDeletesToCompleteForOnu(ctx, intfID, onuID, uniID, pendingFlowDelComplete)
1715 select {
1716 case <-pendingFlowDelComplete:
1717 log.Debugw("all pending flow deletes completed", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1718 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
1719
1720 case <-time.After(10 * time.Second):
1721 log.Errorw("pending flow deletes not completed after timeout", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1722 }
1723 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001724}
1725
1726//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04001727func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001728
1729 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301730 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001731 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301732 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301733 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301734 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04001735
Manikkaraj kb1d51442019-07-23 10:41:02 -04001736 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001737 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
manikkaraj k17652a72019-05-06 09:06:36 -04001738 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
1739 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1740 tpDownloadMsg,
1741 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
1742 f.deviceHandler.deviceType,
1743 onuDevice.Type,
1744 onuDevice.Id,
1745 onuDevice.ProxyAddress.DeviceId, "")
1746 if sendErr != nil {
1747 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1748 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1749 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1750 return sendErr
1751 }
1752 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05301753 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301754}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001755
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301756//UpdateOnuInfo function adds onu info to cache and kvstore
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001757func (f *OpenOltFlowMgr) UpdateOnuInfo(intfID uint32, onuID uint32, serialNum string) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301758
1759 f.lockCache.Lock()
1760 defer f.lockCache.Unlock()
1761 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
1762 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
1763 if err := f.resourceMgr.AddOnuInfo(intfID, onu); err != nil {
1764 log.Errorw("failed to add onu info", log.Fields{"onu": onu})
1765 return
1766 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001767 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
1768}
1769
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301770//addGemPortToOnuInfoMap function adds GEMport to ONU map
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001771func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(intfID uint32, onuID uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301772 f.lockCache.Lock()
1773 defer f.lockCache.Unlock()
1774 onugem := f.onuGemInfo[intfID]
1775 // update the gem to the local cache as well as to kv strore
1776 for idx, onu := range onugem {
1777 if onu.OnuID == onuID {
1778 // check if gem already exists , else update the cache and kvstore
1779 for _, gem := range onu.GemPorts {
1780 if gem == gemPort {
1781 log.Debugw("Gem already in cache, no need to update cache and kv store",
1782 log.Fields{"gem": gemPort})
1783 return
1784 }
1785 }
1786 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
1787 f.onuGemInfo[intfID] = onugem
1788 }
1789 }
1790 err := f.resourceMgr.AddGemToOnuGemInfo(intfID, onuID, gemPort)
1791 if err != nil {
1792 log.Errorw("Failed to add gem to onu", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001793 return
1794 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001795}
1796
1797// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001798
1799//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
1800func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301801
1802 f.lockCache.Lock()
1803 defer f.lockCache.Unlock()
1804
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001805 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 +05301806 // get onuid from the onugem info cache
1807 onugem := f.onuGemInfo[intfID]
1808 for _, onu := range onugem {
1809 for _, gem := range onu.GemPorts {
1810 if gem == gemPortID {
1811 return onu.OnuID, nil
1812 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001813 }
1814 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001815 log.Errorw("onuid is not found", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPort": gemPortID})
1816 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 -04001817}
1818
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001819//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
1820func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001821 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001822 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001823 var err error
1824
1825 if packetIn.IntfType == "pon" {
1826 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001827 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001828 log.Errorw("Unable to get ONU ID from GEM/PON port", log.Fields{"pon port": packetIn.IntfId, "gemport": packetIn.GemportId})
1829 return logicalPortNum, err
1830 }
1831 if packetIn.PortNo != 0 {
1832 logicalPortNum = packetIn.PortNo
1833 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001834 uniID := uint32(0) // FIXME - multi-uni support
1835 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001836 }
1837 // 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 +05301838 f.UpdateGemPortForPktIn(packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001839 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001840 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001841 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001842 log.Debugw("Retrieved logicalport from packet-in", log.Fields{
1843 "logicalPortNum": logicalPortNum,
1844 "IntfType": packetIn.IntfType,
1845 "packet": hex.EncodeToString(packetIn.Pkt),
1846 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001847 return logicalPortNum, nil
1848}
1849
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001850//GetPacketOutGemPortID returns gemPortId
1851func (f *OpenOltFlowMgr) GetPacketOutGemPortID(intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
1852 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001853 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301854
1855 f.lockCache.Lock()
1856 defer f.lockCache.Unlock()
1857 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum}
1858
1859 gemPortID, ok := f.packetInGemPort[pktInkey]
1860 if ok {
1861 log.Debugw("Found gemport for pktin key", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1862 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001863 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301864 //If gem is not found in cache try to get it from kv store, if found in kv store, update the cache and return.
1865 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(intfID, onuID, portNum)
1866 if err == nil {
1867 if gemPortID != 0 {
1868 f.packetInGemPort[pktInkey] = gemPortID
1869 log.Debugw("Found gem port from kv store and updating cache with gemport",
1870 log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1871 return gemPortID, nil
1872 }
1873 }
1874 log.Errorw("Failed to get gemport", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1875 return uint32(0), err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001876}
1877
Manikkaraj kb1d51442019-07-23 10:41:02 -04001878func installFlowOnAllGemports(
1879 f1 func(intfId uint32, onuId uint32, uniId uint32,
1880 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
1881 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32),
1882 f2 func(intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301883 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
1884 classifier map[string]interface{}, action map[string]interface{}),
Manikkaraj kb1d51442019-07-23 10:41:02 -04001885 args map[string]uint32,
1886 classifier map[string]interface{}, action map[string]interface{},
1887 logicalFlow *ofp.OfpFlowStats,
1888 gemPorts []uint32,
1889 FlowType string,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001890 vlanID ...uint32) {
1891 log.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
1892 for _, gemPortID := range gemPorts {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001893 if FlowType == HsiaFlow || FlowType == DhcpFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001894 f1(args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001895 } else if FlowType == EapolFlow {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301896 f2(args["intfId"], args["onuId"], args["uniId"], args["portNo"], logicalFlow, args["allocId"], gemPortID, vlanID[0], classifier, action)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001897 } else {
1898 log.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
1899 return
1900 }
1901 }
1902}
1903
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001904func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
1905 log.Debug("Adding trap-dhcp-of-nni-flow")
1906 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001907 classifier[PacketTagType] = DoubleTag
1908 action[TrapToHost] = true
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301909 var err error
1910 var networkInterfaceID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001911 /* We manage flowId resource pool on per PON port basis.
1912 Since this situation is tricky, as a hack, we pass the NNI port
1913 index (network_intf_id) as PON port Index for the flowId resource
1914 pool. Also, there is no ONU Id available for trapping DHCP packets
1915 on NNI port, use onu_id as -1 (invalid)
1916 ****************** CAVEAT *******************
1917 This logic works if the NNI Port Id falls within the same valid
1918 range of PON Port Ids. If this doesn't work for some OLT Vendor
1919 we need to have a re-look at this.
1920 *********************************************
1921 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001922 onuID := -1
1923 uniID := -1
1924 gemPortID := -1
1925 allocID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301926 networkInterfaceID, err = getNniIntfID(classifier, action)
1927 if err != nil {
1928 log.Error("Failed to get nniIntf ID")
1929 return
1930 }
1931
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001932 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301933 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001934 log.Debug("Flow-exists--not-re-adding")
1935 return
1936 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301937 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001938 if err != nil {
1939 log.Errorw("Flow id unavailable for DHCP traponNNI flow", log.Fields{"error": err})
1940 return
1941 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001942 var classifierProto *openoltpb2.Classifier
1943 var actionProto *openoltpb2.Action
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001944 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
1945 log.Error("Error in making classifier protobuf for dhcp trap on nni flow")
1946 return
1947 }
1948 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1949 if actionProto = makeOpenOltActionField(action); actionProto == nil {
1950 log.Error("Error in making action protobuf for dhcp trap on nni flow")
1951 return
1952 }
1953 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001954 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1955 OnuId: int32(onuID), // OnuId not required
1956 UniId: int32(uniID), // UniId not used
1957 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001958 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001959 AllocId: int32(allocID), // AllocId not used
1960 NetworkIntfId: int32(networkInterfaceID),
1961 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001962 Classifier: classifierProto,
1963 Action: actionProto,
1964 Priority: int32(logicalFlow.Priority),
1965 Cookie: logicalFlow.Cookie,
1966 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001967 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001968 log.Debug("DHCP trap on NNI flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301969 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001970 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1971 int32(onuID),
1972 int32(uniID),
1973 flowID, flowsToKVStore); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001974 log.Errorw("Error uploading DHCP DL flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1975 }
1976 }
1977 return
1978}
salmansiddiqui7ac62132019-08-22 03:58:50 +00001979
Esin Karamanae41e2b2019-12-17 18:13:13 +00001980//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
1981func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
1982 var packetType string
1983 ovid, ivid := false, false
1984 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
1985 vid := vlanID & VlanvIDMask
1986 if vid != ReservedVlan {
1987 ovid = true
1988 }
1989 }
1990 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1991 vid := uint32(metadata)
1992 if vid != ReservedVlan {
1993 ivid = true
1994 }
1995 }
1996 if ovid && ivid {
1997 packetType = DoubleTag
1998 } else if !ovid && !ivid {
1999 packetType = Untagged
2000 } else {
2001 packetType = SingleTag
2002 }
2003 return packetType
2004}
2005
2006//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
2007func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
2008 log.Debugw("Adding igmp-trap-of-nni-flow", log.Fields{"classifierInfo": classifier})
2009 action := make(map[string]interface{})
2010 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2011 action[TrapToHost] = true
2012 /* We manage flowId resource pool on per PON port basis.
2013 Since this situation is tricky, as a hack, we pass the NNI port
2014 index (network_intf_id) as PON port Index for the flowId resource
2015 pool. Also, there is no ONU Id available for trapping packets
2016 on NNI port, use onu_id as -1 (invalid)
2017 ****************** CAVEAT *******************
2018 This logic works if the NNI Port Id falls within the same valid
2019 range of PON Port Ids. If this doesn't work for some OLT Vendor
2020 we need to have a re-look at this.
2021 *********************************************
2022 */
2023 onuID := -1
2024 uniID := -1
2025 gemPortID := -1
2026 allocID := -1
2027 networkInterfaceID, err := getNniIntfID(classifier, action)
2028 if err != nil {
2029 log.Error("Failed to get nniIntf ID")
2030 return
2031 }
2032 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
2033 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
2034 log.Debug("igmp-flow-exists--not-re-adding")
2035 return
2036 }
2037 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
2038 if err != nil {
2039 log.Errorw("IGMP flow id unavailable for trap-on-NNI flow", log.Fields{"error": err})
2040 return
2041 }
2042 var classifierProto *openoltpb2.Classifier
2043 var actionProto *openoltpb2.Action
2044 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
2045 log.Error("Error in making classifier protobuf for igmp trap on nni flow")
2046 return
2047 }
2048 log.Debugw("Created classifier proto for the IGMP flow", log.Fields{"classifier": *classifierProto})
2049 if actionProto = makeOpenOltActionField(action); actionProto == nil {
2050 log.Error("Error in making action protobuf for IGMP trap on nni flow")
2051 return
2052 }
2053 log.Debugw("Created action proto for the IGMP flow", log.Fields{"action": *actionProto})
2054 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2055 OnuId: int32(onuID), // OnuId not required
2056 UniId: int32(uniID), // UniId not used
2057 FlowId: flowID,
2058 FlowType: Downstream,
2059 AllocId: int32(allocID), // AllocId not used
2060 NetworkIntfId: int32(networkInterfaceID),
2061 GemportId: int32(gemPortID), // GemportId not used
2062 Classifier: classifierProto,
2063 Action: actionProto,
2064 Priority: int32(logicalFlow.Priority),
2065 Cookie: logicalFlow.Cookie,
2066 PortNo: portNo}
2067 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
2068 log.Debug("IGMP Trap on NNI flow added to device successfully")
2069 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
2070 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
2071 int32(onuID),
2072 int32(uniID),
2073 flowID, flowsToKVStore); err != nil {
2074 log.Errorw("Error uploading igmp-trap-on-nni flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
2075 }
2076 }
2077 return
2078}
2079
salmansiddiqui7ac62132019-08-22 03:58:50 +00002080func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2081 if MeterID == 0 { // This should never happen
2082 log.Error("Invalid meter id")
2083 return "", errors.New("invalid meter id")
2084 }
2085 if Dir == tp_pb.Direction_UPSTREAM {
2086 return "upstream", nil
2087 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2088 return "downstream", nil
2089 }
2090 return "", nil
2091}
2092
2093func (f *OpenOltFlowMgr) checkAndAddFlow(args map[string]uint32, classifierInfo map[string]interface{},
Gamze Abakafee36392019-10-03 11:17:24 +00002094 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst *tp.TechProfile, gemPorts []uint32,
2095 TpID uint32, uni string) {
2096 var gemPort uint32
2097 intfID := args[IntfID]
2098 onuID := args[OnuID]
2099 uniID := args[UniID]
2100 portNo := args[PortNo]
2101 allocID := TpInst.UsScheduler.AllocID
salmansiddiqui7ac62132019-08-22 03:58:50 +00002102 if ipProto, ok := classifierInfo[IPProto]; ok {
2103 if ipProto.(uint32) == IPProtoDhcp {
2104 log.Info("Adding DHCP flow")
2105 if pcp, ok := classifierInfo[VlanPcp]; ok {
2106 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2107 tp_pb.Direction_UPSTREAM,
2108 pcp.(uint32))
2109 //Adding DHCP upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00002110 f.addDHCPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002111 } else {
2112 //Adding DHCP upstream flow to all gemports
2113 installFlowOnAllGemports(f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, DhcpFlow)
2114 }
2115
2116 } else if ipProto == IgmpProto {
Esin Karamanae41e2b2019-12-17 18:13:13 +00002117 log.Infow("Adding Us IGMP flow", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "classifierInfo:": classifierInfo})
2118 if pcp, ok := classifierInfo[VlanPcp]; ok {
2119 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2120 tp_pb.Direction_UPSTREAM,
2121 pcp.(uint32))
2122 f.addIGMPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
2123 } else {
2124 //Adding IGMP upstream flow to all gem ports
2125 installFlowOnAllGemports(f.addIGMPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, IgmpFlow)
2126 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002127 } else {
2128 log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
2129 return
2130 }
2131 } else if ethType, ok := classifierInfo[EthType]; ok {
2132 if ethType.(uint32) == EapEthType {
2133 log.Info("Adding EAPOL flow")
2134 var vlanID uint32
2135 if val, ok := classifierInfo[VlanVid]; ok {
2136 vlanID = (val.(uint32)) & VlanvIDMask
2137 } else {
2138 vlanID = DefaultMgmtVlan
2139 }
2140 if pcp, ok := classifierInfo[VlanPcp]; ok {
2141 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2142 tp_pb.Direction_UPSTREAM,
2143 pcp.(uint32))
2144
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302145 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID, gemPort, vlanID, classifierInfo, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002146 } else {
2147 installFlowOnAllGemports(nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, EapolFlow, vlanID)
2148 }
2149 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002150 } else if _, ok := actionInfo[PushVlan]; ok {
2151 log.Info("Adding upstream data rule")
2152 if pcp, ok := classifierInfo[VlanPcp]; ok {
2153 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2154 tp_pb.Direction_UPSTREAM,
2155 pcp.(uint32))
2156 //Adding HSIA upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00002157 f.addUpstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002158 } else {
2159 //Adding HSIA upstream flow to all gemports
2160 installFlowOnAllGemports(f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
2161 }
2162 } else if _, ok := actionInfo[PopVlan]; ok {
2163 log.Info("Adding Downstream data rule")
2164 if pcp, ok := classifierInfo[VlanPcp]; ok {
2165 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05002166 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00002167 pcp.(uint32))
2168 //Adding HSIA downstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00002169 f.addDownstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002170 } else {
2171 //Adding HSIA downstream flow to all gemports
2172 installFlowOnAllGemports(f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
2173 }
2174 } else {
2175 log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
2176 return
2177 }
2178 // Send Techprofile download event to child device in go routine as it takes time
2179 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, TpID)
2180}
2181
Gamze Abakafee36392019-10-03 11:17:24 +00002182func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
2183 flowIDList := f.flowsUsedByGemPort[gemPK]
2184 if len(flowIDList) > 1 {
2185 return true
2186 }
2187 return false
2188}
2189
Girish Gowdra54934262019-11-13 14:19:55 +05302190func (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 +00002191 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ponIntf, onuID, uniID)
2192 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2193 for _, currentGemPort := range currentGemPorts {
2194 for _, tpGemPort := range tpGemPorts {
2195 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
2196 return true, currentGemPort
2197 }
2198 }
2199 }
Girish Gowdra54934262019-11-13 14:19:55 +05302200 if tpInst.InstanceCtrl.Onu == "single-instance" {
2201 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
2202 f.resourceMgr.RemoveTechProfileIDForOnu(ponIntf, uint32(onuID), uint32(uniID), tpID)
2203 f.DeleteTechProfileInstance(ponIntf, uint32(onuID), uint32(uniID), "", tpID)
2204
2205 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
2206 // still be used on other uni ports.
2207 // So, we need to check and make sure that no other gem port is referring to the given TP ID
2208 // on any other uni port.
2209 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(tpID, ponIntf, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05302210 log.Debugw("got single instance tp instances", log.Fields{"tpInstances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05302211 for i := 0; i < len(tpInstances); i++ {
2212 tpI := tpInstances[i]
2213 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05302214 for _, tpGemPort := range tpGemPorts {
2215 if tpGemPort.GemportID != gemPortID {
2216 log.Debugw("single instance tp is in use by gem", log.Fields{"gemPort": tpGemPort.GemportID})
2217 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05302218 }
2219 }
2220 }
2221 }
Girish Gowdra6b130582019-11-20 16:45:20 +05302222 log.Debug("tech profile is not in use by any gem")
Gamze Abakafee36392019-10-03 11:17:24 +00002223 return false, 0
2224}
2225
salmansiddiqui7ac62132019-08-22 03:58:50 +00002226func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002227 for _, field := range flows.GetOfbFields(flow) {
2228 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002229 classifierInfo[EthType] = field.GetEthType()
2230 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002231 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002232 classifierInfo[IPProto] = field.GetIpProto()
2233 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002234 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002235 classifierInfo[InPort] = field.GetPort()
2236 log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002237 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05302238 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
salmansiddiqui7ac62132019-08-22 03:58:50 +00002239 log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002240 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002241 classifierInfo[VlanPcp] = field.GetVlanPcp()
2242 log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002243 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002244 classifierInfo[UDPDst] = field.GetUdpDst()
2245 log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002246 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002247 classifierInfo[UDPSrc] = field.GetUdpSrc()
2248 log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002249 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002250 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
2251 log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002252 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002253 classifierInfo[Ipv4Src] = field.GetIpv4Src()
2254 log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002255 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002256 classifierInfo[Metadata] = field.GetTableMetadata()
2257 log.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07002258 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002259 classifierInfo[TunnelID] = field.GetTunnelId()
2260 log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
2261 } else {
2262 log.Errorw("Un supported field type", log.Fields{"type": field.Type})
2263 return
2264 }
2265 }
2266}
2267
2268func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07002269 for _, action := range flows.GetActions(flow) {
2270 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002271 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002272 actionInfo[Output] = out.GetPort()
2273 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002274 } else {
2275 log.Error("Invalid output port in action")
2276 return errors.New("invalid output port in action")
2277 }
Scott Baker355d1742019-10-24 10:57:52 -07002278 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002279 actionInfo[PopVlan] = true
2280 log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002281 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002282 if out := action.GetPush(); out != nil {
2283 if tpid := out.GetEthertype(); tpid != 0x8100 {
2284 log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
2285 } else {
2286 actionInfo[PushVlan] = true
2287 actionInfo[TPID] = tpid
2288 log.Debugw("action-type-push-vlan",
2289 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
2290 }
2291 }
Scott Baker355d1742019-10-24 10:57:52 -07002292 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002293 if out := action.GetSetField(); out != nil {
2294 if field := out.GetField(); field != nil {
2295 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
2296 log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
2297 return errors.New("invalid openflow class")
2298 }
2299 /*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
2300 if ofbField := field.GetOfbField(); ofbField != nil {
2301 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
2302 if vlan := ofbField.GetVlanVid(); vlan != 0 {
2303 actionInfo[VlanVid] = vlan & 0xfff
2304 log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
2305 } else {
2306 log.Error("No Invalid vlan id in set vlan-vid action")
2307 }
2308 } else {
2309 log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
2310 }
2311 }
2312 }
2313 }
2314 } else {
2315 log.Errorw("Un supported action type", log.Fields{"type": action.Type})
2316 return errors.New("un supported action type")
2317 }
2318 }
2319 return nil
2320}
2321
2322func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002323 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002324 log.Debug("Controller bound trap flows, getting inport from tunnelid")
2325 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2326 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002327 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002328 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07002329 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 +00002330 } else {
2331 log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
2332 return errors.New("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
2333 }
2334 }
2335 } else {
2336 log.Debug("Non-Controller flows, getting uniport from tunnelid")
2337 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07002338 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002339 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002340 actionInfo[Output] = uniPort
2341 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 +00002342 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002343 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 +00002344 return errors.New("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid")
2345 }
2346 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2347 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002348 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002349 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07002350 log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[Output].(uint32),
2351 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002352 } else {
2353 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 -07002354 "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002355 return errors.New("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid")
2356 }
2357 }
2358 }
2359 return nil
2360}
Gamze Abakafee36392019-10-03 11:17:24 +00002361
Chaitrashree G S90a17952019-11-14 21:51:21 -05002362func getTpIDFromFlow(flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00002363 /* Metadata 8 bytes:
2364 Most Significant 2 Bytes = Inner VLAN
2365 Next 2 Bytes = Tech Profile ID(TPID)
2366 Least Significant 4 Bytes = Port ID
2367 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
2368 subscriber related flows.
2369 */
2370 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
2371 if metadata == 0 {
Chaitrashree G S90a17952019-11-14 21:51:21 -05002372 log.Error("metadata-is-not-present-in-flow-which-is-mandatory")
2373 return 0, errors.New("metadata-is-not-present-in-flow-which-is-mandatory")
Gamze Abakafee36392019-10-03 11:17:24 +00002374 }
2375 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002376 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00002377}
2378
2379func appendUnique(slice []uint32, item uint32) []uint32 {
2380 for _, sliceElement := range slice {
2381 if sliceElement == item {
2382 return slice
2383 }
2384 }
2385 return append(slice, item)
2386}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302387
2388// getNniIntfID gets nni intf id from the flow classifier/action
2389func getNniIntfID(classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
2390
2391 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
2392 if portType == voltha.Port_PON_OLT {
2393 intfID := IntfIDFromNniPortNum(action[Output].(uint32))
2394 log.Debugw("output Nni IntfID is", log.Fields{"intfid": intfID})
2395 return intfID, nil
2396 } else if portType == voltha.Port_ETHERNET_NNI {
2397 intfID := IntfIDFromNniPortNum(classifier[InPort].(uint32))
2398 log.Debugw("input Nni IntfID is", log.Fields{"intfid": intfID})
2399 return intfID, nil
2400 }
2401 return uint32(0), nil
2402}
2403
2404// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
2405func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32) {
2406 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort}
2407
2408 f.lockCache.Lock()
2409 defer f.lockCache.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05002410 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302411 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05002412 if lookupGemPort == gemPort {
2413 log.Debugw("pktin key/value found in cache , no need to update kv as we are assuming both will be in sync",
2414 log.Fields{"pktinkey": pktInkey, "gem": gemPort})
2415 return
2416 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302417 }
Matt Jeanneret1719a072019-12-20 14:50:14 -05002418 f.packetInGemPort[pktInkey] = gemPort
2419
2420 f.resourceMgr.UpdateGemPortForPktIn(pktInkey, gemPort)
2421 log.Debugw("pktin key not found in local cache or value is different. updating cache and kv store", log.Fields{"pktinkey": pktInkey, "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302422 return
2423}
2424
2425// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
2426func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(intfID uint32, onuID uint32, portNum uint32) {
2427
2428 f.lockCache.Lock()
2429 defer f.lockCache.Unlock()
2430 onugem := f.onuGemInfo[intfID]
2431 for idx, onu := range onugem {
2432 if onu.OnuID == onuID {
2433 for _, uni := range onu.UniPorts {
2434 if uni == portNum {
2435 log.Debugw("uni already in cache, no need to update cache and kv store",
2436 log.Fields{"uni": portNum})
2437 return
2438 }
2439 }
2440 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
2441 f.onuGemInfo[intfID] = onugem
2442 }
2443 }
2444 f.resourceMgr.AddUniPortToOnuInfo(intfID, onuID, portNum)
2445}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302446
2447func (f *OpenOltFlowMgr) loadFlowIDlistForGem(intf uint32) {
2448 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(intf)
2449 if err != nil {
2450 log.Error("Failed to get flowid list per gem", log.Fields{"intf": intf})
2451 return
2452 }
2453 for gem, FlowIDs := range flowIDsList {
2454 gemPK := gemPortKey{intf, uint32(gem)}
2455 f.flowsUsedByGemPort[gemPK] = FlowIDs
2456 }
2457 return
2458}