blob: ef6dad549c999123a112d52ccec99be195e8176d [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 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001176 f.registerFlow(logicalFlow, deviceFlow)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301177 log.Debugw("Flow added to device successfully ", log.Fields{"flow": *deviceFlow})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001178 return true
1179}
1180
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001181func (f *OpenOltFlowMgr) removeFlowFromDevice(deviceFlow *openoltpb2.Flow) bool {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001182 log.Debugw("Sending flow to device via grpc", log.Fields{"flow": *deviceFlow})
1183 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1184 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001185 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
1186 log.Warnw("Can not remove flow from device since it's unreachable", log.Fields{"err": err, "deviceFlow": deviceFlow})
1187 //Assume the flow is removed
1188 return true
1189 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001190 log.Errorw("Failed to Remove flow from device", log.Fields{"err": err, "deviceFlow": deviceFlow})
1191 return false
serkant.uluderya245caba2019-09-24 23:15:29 -07001192
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001193 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001194 log.Debugw("Flow removed from device successfully ", log.Fields{"flow": *deviceFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301195 return true
1196}
1197
1198/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1199 //update core flows_proxy : flows_proxy.update('/', flows)
1200}
1201
1202func generateStoredId(flowId uint32, direction string)uint32{
1203
David K. Bainbridge82efc492019-09-04 09:57:11 -07001204 if direction == Upstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301205 log.Debug("Upstream flow shifting flowid")
1206 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001207 }else if direction == Downstream{
manikkaraj kbf256be2019-03-25 00:13:48 +05301208 log.Debug("Downstream flow not shifting flowid")
1209 return flowId
1210 }else{
1211 log.Errorw("Unrecognized direction",log.Fields{"direction": direction})
1212 return flowId
1213 }
1214}
1215
1216*/
1217
Humera Kouser94d7a842019-08-25 19:04:32 -04001218func (f *OpenOltFlowMgr) addLLDPFlow(flow *ofp.OfpFlowStats, portNo uint32) {
1219
1220 classifierInfo := make(map[string]interface{})
1221 actionInfo := make(map[string]interface{})
1222
1223 classifierInfo[EthType] = uint32(LldpEthType)
1224 classifierInfo[PacketTagType] = Untagged
1225 actionInfo[TrapToHost] = true
1226
1227 // LLDP flow is installed to trap LLDP packets on the NNI port.
1228 // We manage flow_id resource pool on per PON port basis.
1229 // Since this situation is tricky, as a hack, we pass the NNI port
1230 // index (network_intf_id) as PON port Index for the flow_id resource
1231 // pool. Also, there is no ONU Id available for trapping LLDP packets
1232 // on NNI port, use onu_id as -1 (invalid)
1233 // ****************** CAVEAT *******************
1234 // This logic works if the NNI Port Id falls within the same valid
1235 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1236 // we need to have a re-look at this.
1237 // *********************************************
1238
1239 var onuID = -1
1240 var uniID = -1
1241 var gemPortID = -1
1242
1243 var networkInterfaceID = IntfIDFromNniPortNum(portNo)
1244 var flowStoreCookie = getFlowStoreCookie(classifierInfo, uint32(0))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301245 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Humera Kouser94d7a842019-08-25 19:04:32 -04001246 log.Debug("Flow-exists--not-re-adding")
1247 return
1248 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301249 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001250
1251 if err != nil {
1252 log.Errorw("Flow id unavailable for LLDP traponNNI flow", log.Fields{"error": err})
1253 return
1254 }
1255 var classifierProto *openoltpb2.Classifier
1256 var actionProto *openoltpb2.Action
1257 if classifierProto = makeOpenOltClassifierField(classifierInfo); classifierProto == nil {
1258 log.Error("Error in making classifier protobuf for LLDP trap on nni flow")
1259 return
1260 }
1261 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1262 if actionProto = makeOpenOltActionField(actionInfo); actionProto == nil {
1263 log.Error("Error in making action protobuf for LLDP trap on nni flow")
1264 return
1265 }
1266 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
1267
1268 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1269 OnuId: int32(onuID), // OnuId not required
1270 UniId: int32(uniID), // UniId not used
1271 FlowId: flowID,
1272 FlowType: Downstream,
1273 NetworkIntfId: int32(networkInterfaceID),
1274 GemportId: int32(gemPortID),
1275 Classifier: classifierProto,
1276 Action: actionProto,
1277 Priority: int32(flow.Priority),
1278 Cookie: flow.Cookie,
1279 PortNo: portNo}
1280 if ok := f.addFlowToDevice(flow, &downstreamflow); ok {
1281 log.Debug("LLDP trap on NNI flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301282 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID, flow.Id)
Humera Kouser94d7a842019-08-25 19:04:32 -04001283 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1284 int32(onuID),
1285 int32(uniID),
1286 flowID, flowsToKVStore); err != nil {
1287 log.Errorw("Error uploading LLDP flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1288 }
1289 }
1290 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301291}
1292
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301293func getUniPortPath(intfID uint32, onuID int32, uniID int32) string {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001294 return fmt.Sprintf("pon-{%d}/onu-{%d}/uni-{%d}", intfID, onuID, uniID)
1295}
1296
1297//getOnuChildDevice to fetch onu
1298func (f *OpenOltFlowMgr) getOnuChildDevice(intfID uint32, onuID uint32) (*voltha.Device, error) {
1299 log.Debugw("GetChildDevice", log.Fields{"pon port": intfID, "onuId": onuID})
1300 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
1301 onuDevice := f.deviceHandler.GetChildDevice(parentPortNo, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301302 if onuDevice == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001303 log.Errorw("onu not found", log.Fields{"intfId": parentPortNo, "onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301304 return nil, errors.New("onu not found")
manikkaraj kbf256be2019-03-25 00:13:48 +05301305 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301306 log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
1307 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301308}
1309
1310func findNextFlow(flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001311 log.Info("unimplemented flow : %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301312 return nil
1313}
1314
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001315func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
1316 log.Info("unimplemented device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301317}
1318
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001319func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001320 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001321 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001322 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001323 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001324}
1325
Girish Gowdra6b130582019-11-20 16:45:20 +05301326func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1327 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
1328 if err != nil {
1329 log.Errorw("error fetching child device from core", log.Fields{"onuId": onuID})
1330 return err
1331 }
1332
1333 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
1334 log.Debugw("sending gem port delete to openonu adapter", log.Fields{"msg": *delGemPortMsg})
1335 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1336 delGemPortMsg,
1337 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
1338 f.deviceHandler.deviceType,
1339 onuDevice.Type,
1340 onuDevice.Id,
1341 onuDevice.ProxyAddress.DeviceId, ""); sendErr != nil {
1342 log.Errorw("failure sending del gem port to onu adapter", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1343 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1344 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1345 return sendErr
1346 }
1347 log.Debugw("success sending del gem port to onu adapter", log.Fields{"msg": delGemPortMsg})
1348 return nil
1349}
1350
1351func (f *OpenOltFlowMgr) sendDeleteTcontToChild(intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1352 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
1353 if err != nil {
1354 log.Errorw("error fetching child device from core", log.Fields{"onuId": onuID})
1355 return err
1356 }
1357
1358 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
1359 log.Debugw("sending tcont delete to openonu adapter", log.Fields{"msg": *delTcontMsg})
1360 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1361 delTcontMsg,
1362 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
1363 f.deviceHandler.deviceType,
1364 onuDevice.Type,
1365 onuDevice.Id,
1366 onuDevice.ProxyAddress.DeviceId, ""); sendErr != nil {
1367 log.Errorw("failure sending del tcont to onu adapter", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1368 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1369 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1370 return sendErr
1371 }
1372 log.Debugw("success sending del tcont to onu adapter", log.Fields{"msg": delTcontMsg})
1373 return nil
1374}
1375
Girish Gowdra3d633032019-12-10 16:37:05 +05301376func (f *OpenOltFlowMgr) deletePendingFlows(Intf uint32, onuID int32, uniID int32) {
1377 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1378 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); ok {
1379 if val.(int) > 0 {
1380 pnFlDels := val.(int) - 1
1381 if pnFlDels > 0 {
1382 log.Debugw("flow delete succeeded, more pending",
1383 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID, "currPendingFlowCnt": pnFlDels})
1384 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1385 } else {
1386 log.Debugw("all pending flow deletes handled, removing entry from map",
1387 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1388 f.pendingFlowDelete.Delete(pnFlDelKey)
1389 }
1390 }
1391 } else {
1392 log.Debugw("no pending delete flows found",
1393 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1394
1395 }
1396
1397}
1398
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301399//clearResources clears pon resources in kv store and the device
1400func (f *OpenOltFlowMgr) clearResources(flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
1401 gemPortID int32, flowID uint32, flowDirection string,
1402 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001403
Chaitrashree G S90a17952019-11-14 21:51:21 -05001404 tpID, err := getTpIDFromFlow(flow)
1405 if err != nil {
1406 log.Error("metadata-is-not-present-invalid-flow-to-process", log.Fields{"pon": Intf, "onuID": onuID, "uniID": uniID})
1407 return err
1408 }
Gamze Abakafee36392019-10-03 11:17:24 +00001409
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001410 if len(updatedFlows) >= 0 {
1411 // There are still flows referencing the same flow_id.
1412 // So the flow should not be freed yet.
1413 // For ex: Case of HSIA where same flow is shared
1414 // between DS and US.
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301415 f.updateFlowInfoToKVStore(int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001416 if len(updatedFlows) == 0 {
Girish Gowdra3d633032019-12-10 16:37:05 +05301417 // Do this for subscriber flows only (not trap from NNI flows)
1418 if onuID != -1 && uniID != -1 {
1419 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1420 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
1421 log.Debugw("creating entry for pending flow delete",
1422 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID})
1423 f.pendingFlowDelete.Store(pnFlDelKey, 1)
1424 } else {
1425 pnFlDels := val.(int) + 1
1426 log.Debugw("updating flow delete entry",
1427 log.Fields{"intf": Intf, "onuID": onuID, "uniID": uniID, "currPendingFlowCnt": pnFlDels})
1428 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1429 }
1430
1431 defer f.deletePendingFlows(Intf, onuID, uniID)
1432 }
1433
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301434 log.Debugw("Releasing flow Id to resource manager", log.Fields{"Intf": Intf, "onuId": onuID, "uniId": uniID, "flowId": flowID})
1435 f.resourceMgr.FreeFlowID(Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001436
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301437 uni := getUniPortPath(Intf, onuID, uniID)
1438 tpPath := f.getTPpath(Intf, uni, tpID)
Gamze Abakafee36392019-10-03 11:17:24 +00001439 log.Debugw("Getting-techprofile-instance-for-subscriber", log.Fields{"TP-PATH": tpPath})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301440 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(tpID, tpPath)
Gamze Abakafee36392019-10-03 11:17:24 +00001441 if err != nil { // This should not happen, something wrong in KV backend transaction
1442 log.Errorw("Error in fetching tech profile instance from KV store", log.Fields{"tpID": 20, "path": tpPath})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301443 return err
Gamze Abakafee36392019-10-03 11:17:24 +00001444 }
1445 if techprofileInst == nil {
1446 log.Errorw("Tech-profile-instance-does-not-exist-in-KV Store", log.Fields{"tpPath": tpPath})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301447 return err
Gamze Abakafee36392019-10-03 11:17:24 +00001448 }
1449
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301450 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00001451 if f.isGemPortUsedByAnotherFlow(gemPK) {
1452 flowIDs := f.flowsUsedByGemPort[gemPK]
1453 for i, flowIDinMap := range flowIDs {
1454 if flowIDinMap == flowID {
1455 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301456 // everytime flowsUsedByGemPort cache is updated the same should be updated
1457 // in kv store by calling UpdateFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001458 f.flowsUsedByGemPort[gemPK] = flowIDs
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301459 f.resourceMgr.UpdateFlowIDsForGem(Intf, uint32(gemPortID), flowIDs)
Gamze Abakafee36392019-10-03 11:17:24 +00001460 break
1461 }
1462 }
1463 log.Debugw("Gem port id is still used by other flows", log.Fields{"gemPortID": gemPortID, "usedByFlows": flowIDs})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301464 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00001465 }
Gamze Abakafee36392019-10-03 11:17:24 +00001466 log.Debugf("Gem port id %d is not used by another flow - releasing the gem port", gemPortID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301467 f.resourceMgr.RemoveGemPortIDForOnu(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001468 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1469 // 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 +05301470 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(uint32(gemPortID), Intf)
Gamze Abakafee36392019-10-03 11:17:24 +00001471 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301472 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1473 // by calling DeleteFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00001474 delete(f.flowsUsedByGemPort, gemPK)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301475 f.resourceMgr.DeleteFlowIDsForGem(Intf, uint32(gemPortID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301476 f.resourceMgr.FreeGemPortID(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001477 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05301478 // Delete the gem port on the ONU.
1479 if err := f.sendDeleteGemPortToChild(Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
1480 log.Errorw("error processing delete gem-port towards onu",
1481 log.Fields{"err": err, "pon": Intf, "onuID": onuID, "uniID": uniID, "gemPortId": gemPortID})
1482 }
Gamze Abakafee36392019-10-03 11:17:24 +00001483
Girish Gowdra54934262019-11-13 14:19:55 +05301484 ok, _ := f.isTechProfileUsedByAnotherGem(Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00001485 if !ok {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301486 f.resourceMgr.RemoveTechProfileIDForOnu(Intf, uint32(onuID), uint32(uniID), tpID)
1487 f.RemoveSchedulerQueues(schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1488 f.RemoveSchedulerQueues(schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
1489 f.DeleteTechProfileInstance(Intf, uint32(onuID), uint32(uniID), "", tpID)
1490 f.resourceMgr.FreeAllocID(Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301491 // Delete the TCONT on the ONU.
1492 if err := f.sendDeleteTcontToChild(Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
1493 log.Errorw("error processing delete tcont towards onu",
1494 log.Fields{"pon": Intf, "onuID": onuID, "uniID": uniID, "allocId": techprofileInst.UsScheduler.AllocID})
1495 }
Gamze Abakafee36392019-10-03 11:17:24 +00001496 }
1497 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001498 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301499 return nil
1500}
1501
1502func (f *OpenOltFlowMgr) clearFlowFromResourceManager(flow *ofp.OfpFlowStats, flowDirection string) {
1503
1504 log.Debugw("clearFlowFromResourceManager", log.Fields{"flowDirection": flowDirection, "flow": *flow})
1505 var updatedFlows []rsrcMgr.FlowInfo
1506 var flowID uint32
1507 var onuID, uniID int32
1508 classifierInfo := make(map[string]interface{})
1509
1510 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(flow, flowDirection)
1511 if err != nil {
1512 log.Error(err)
1513 return
1514 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301515
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301516 onuID = int32(onu)
1517 uniID = int32(uni)
1518
1519 for _, field := range flows.GetOfbFields(flow) {
1520 if field.Type == flows.IP_PROTO {
1521 classifierInfo[IPProto] = field.GetIpProto()
1522 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
1523 }
1524 }
1525 log.Debugw("Extracted access info from flow to be deleted",
1526 log.Fields{"ponIntf": Intf, "onuID": onuID, "uniID": uniID})
1527
1528 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1529 onuID = -1
1530 uniID = -1
1531 log.Debug("Trap on nni flow set oni, uni to -1")
1532 Intf = IntfIDFromNniPortNum(inPort)
1533 }
1534 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(Intf, onuID, uniID)
1535 for _, flowID = range flowIds {
1536 flowInfo := f.resourceMgr.GetFlowIDInfo(Intf, onuID, uniID, flowID)
1537 if flowInfo == nil {
1538 log.Debugw("No FlowInfo found found in KV store",
1539 log.Fields{"Intf": Intf, "onuID": onuID, "uniID": uniID, "flowID": flowID})
1540 return
1541 }
1542 updatedFlows = nil
1543 for _, flow := range *flowInfo {
1544 updatedFlows = append(updatedFlows, flow)
1545 }
1546
1547 for i, storedFlow := range updatedFlows {
1548 if flow.Id == storedFlow.LogicalFlowID {
1549 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
1550 log.Debugw("Flow to be deleted", log.Fields{"flow": storedFlow})
1551 if ok := f.removeFlowFromDevice(&removeFlowMessage); ok {
1552 log.Debug("Flow removed from device successfully")
1553 //Remove the Flow from FlowInfo
1554 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
1555 err = f.clearResources(flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
1556 flowID, flowDirection, portNum, updatedFlows)
1557 if err != nil {
1558 log.Error("Failed to clear resources for flow", log.Fields{"flow": storedFlow})
1559 return
1560 }
1561 } else {
1562 log.Error("Failed to remove flow from device")
1563 return
1564 }
1565 }
1566 }
1567 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001568}
1569
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001570//RemoveFlow removes the flow from the device
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001571func (f *OpenOltFlowMgr) RemoveFlow(flow *ofp.OfpFlowStats) {
1572 log.Debugw("Removing Flow", log.Fields{"flow": flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301573 var direction string
1574 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001575
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301576 for _, action := range flows.GetActions(flow) {
1577 if action.Type == flows.OUTPUT {
1578 if out := action.GetOutput(); out != nil {
1579 actionInfo[Output] = out.GetPort()
1580 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
1581 } else {
1582 log.Error("Invalid output port in action")
1583 return
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001584 }
1585 }
1586 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301587 if IsUpstream(actionInfo[Output].(uint32)) {
1588 direction = Upstream
1589 } else {
1590 direction = Downstream
1591 }
1592
1593 f.clearFlowFromResourceManager(flow, direction) //TODO: Take care of the limitations
1594
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001595 return
1596}
1597
Girish Gowdra3d633032019-12-10 16:37:05 +05301598func (f *OpenOltFlowMgr) waitForFlowDeletesToCompleteForOnu(ctx context.Context, intfID uint32, onuID uint32,
1599 uniID uint32, ch chan bool) {
1600 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
1601 for {
1602 select {
1603 case <-time.After(20 * time.Millisecond):
1604 if flowDelRefCnt, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok || flowDelRefCnt == 0 {
1605 log.Debug("pending flow deletes completed")
1606 ch <- true
1607 return
1608 }
1609 case <-ctx.Done():
1610 log.Error("flow delete wait handler routine canceled")
1611 return
1612 }
1613 }
1614}
1615
Esin Karamanae41e2b2019-12-17 18:13:13 +00001616//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
1617func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
1618 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
1619 if ethType, ok := classifierInfo[EthType]; ok {
1620 if ethType.(uint32) == IPv4EthType {
1621 if ipProto, ok := classifierInfo[IPProto]; ok {
1622 if ipProto.(uint32) == IgmpProto {
1623 return true
1624 }
1625 }
1626 }
1627 }
1628 }
1629 return false
1630}
1631
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001632// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05301633// nolint: gocyclo
Manikkaraj kb1d51442019-07-23 10:41:02 -04001634func (f *OpenOltFlowMgr) AddFlow(flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001635 classifierInfo := make(map[string]interface{})
1636 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001637 var UsMeterID uint32
1638 var DsMeterID uint32
1639
1640 log.Debug("Adding Flow", log.Fields{"flow": flow, "flowMetadata": flowMetadata})
salmansiddiqui7ac62132019-08-22 03:58:50 +00001641 formulateClassifierInfoFromFlow(classifierInfo, flow)
1642
1643 err := formulateActionInfoFromFlow(actionInfo, classifierInfo, flow)
1644 if err != nil {
1645 // Error logging is already done in the called function
1646 // So just return in case of error
1647 return
manikkaraj kbf256be2019-03-25 00:13:48 +05301648 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001649
manikkaraj k17652a72019-05-06 09:06:36 -04001650 /* Controller bound trap flows */
salmansiddiqui7ac62132019-08-22 03:58:50 +00001651 err = formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo, flow)
1652 if err != nil {
1653 // error if any, already logged in the called function
1654 return
manikkaraj k17652a72019-05-06 09:06:36 -04001655 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001656
David K. Bainbridge82efc492019-09-04 09:57:11 -07001657 log.Infow("Flow ports", log.Fields{"classifierInfo_inport": classifierInfo[InPort], "action_output": actionInfo[Output]})
1658 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00001659
Humera Kouser94d7a842019-08-25 19:04:32 -04001660 if ethType, ok := classifierInfo[EthType]; ok {
1661 if ethType.(uint32) == LldpEthType {
1662 log.Info("Adding LLDP flow")
1663 f.addLLDPFlow(flow, portNo)
1664 return
1665 }
1666 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001667 if ipProto, ok := classifierInfo[IPProto]; ok {
1668 if ipProto.(uint32) == IPProtoDhcp {
1669 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05301670 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001671 log.Debug("trap-dhcp-from-nni-flow")
1672 f.addDHCPTrapFlowOnNNI(flow, classifierInfo, portNo)
1673 return
1674 }
1675 }
1676 }
1677 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001678 if isIgmpTrapDownstreamFlow(classifierInfo) {
1679 log.Debug("trap-igmp-from-nni-flow")
1680 f.addIgmpTrapFlowOnNNI(flow, classifierInfo, portNo)
1681 return
1682 }
A R Karthick1f85b802019-10-11 05:06:05 +00001683
1684 f.deviceHandler.AddUniPortToOnu(intfID, onuID, portNo)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301685 f.resourceMgr.AddUniPortToOnuInfo(intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00001686
Chaitrashree G S90a17952019-11-14 21:51:21 -05001687 TpID, err := getTpIDFromFlow(flow)
1688 if err != nil {
1689 log.Error("metadata-is-not-present-invalid-flow-to-process", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1690 return
1691 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00001692 log.Debugw("TPID for this subcriber", log.Fields{"TpId": TpID, "pon": intfID, "onuID": onuID, "uniID": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07001693 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07001694 UsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001695 log.Debugw("Upstream-flow-meter-id", log.Fields{"UsMeterID": UsMeterID})
1696 } else {
Scott Baker355d1742019-10-24 10:57:52 -07001697 DsMeterID = flows.GetMeterIdFromFlow(flow)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001698 log.Debugw("Downstream-flow-meter-id", log.Fields{"DsMeterID": DsMeterID})
1699
1700 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301701
1702 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
1703 if _, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
1704 log.Debugw("no pending flows found, going ahead with flow install", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1705 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
1706 } else {
1707 ctx := context.Background()
1708 ctx, cancel := context.WithCancel(ctx)
1709 defer cancel()
1710 pendingFlowDelComplete := make(chan bool)
1711 go f.waitForFlowDeletesToCompleteForOnu(ctx, intfID, onuID, uniID, pendingFlowDelComplete)
1712 select {
1713 case <-pendingFlowDelComplete:
1714 log.Debugw("all pending flow deletes completed", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1715 f.divideAndAddFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
1716
1717 case <-time.After(10 * time.Second):
1718 log.Errorw("pending flow deletes not completed after timeout", log.Fields{"pon": intfID, "onuID": onuID, "uniID": uniID})
1719 }
1720 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001721}
1722
1723//sendTPDownloadMsgToChild send payload
Manikkaraj kb1d51442019-07-23 10:41:02 -04001724func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001725
1726 onuDevice, err := f.getOnuChildDevice(intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05301727 if err != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001728 log.Errorw("Error while fetching Child device from core", log.Fields{"onuId": onuID})
Manikkaraj k884c1242019-04-11 16:26:42 +05301729 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05301730 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301731 log.Debugw("Got child device from OLT device handler", log.Fields{"device": *onuDevice})
manikkaraj k17652a72019-05-06 09:06:36 -04001732
Manikkaraj kb1d51442019-07-23 10:41:02 -04001733 tpPath := f.getTPpath(intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001734 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
manikkaraj k17652a72019-05-06 09:06:36 -04001735 log.Infow("Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": *tpDownloadMsg})
1736 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1737 tpDownloadMsg,
1738 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
1739 f.deviceHandler.deviceType,
1740 onuDevice.Type,
1741 onuDevice.Id,
1742 onuDevice.ProxyAddress.DeviceId, "")
1743 if sendErr != nil {
1744 log.Errorw("send techprofile-download request error", log.Fields{"fromAdapter": f.deviceHandler.deviceType,
1745 "toAdapter": onuDevice.Type, "onuId": onuDevice.Id,
1746 "proxyDeviceId": onuDevice.ProxyAddress.DeviceId})
1747 return sendErr
1748 }
1749 log.Debugw("success Sending Load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"msg": tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05301750 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301751}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001752
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301753//UpdateOnuInfo function adds onu info to cache and kvstore
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001754func (f *OpenOltFlowMgr) UpdateOnuInfo(intfID uint32, onuID uint32, serialNum string) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301755
1756 f.lockCache.Lock()
1757 defer f.lockCache.Unlock()
1758 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
1759 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
1760 if err := f.resourceMgr.AddOnuInfo(intfID, onu); err != nil {
1761 log.Errorw("failed to add onu info", log.Fields{"onu": onu})
1762 return
1763 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001764 log.Debugw("Updated onuinfo", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum})
1765}
1766
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301767//addGemPortToOnuInfoMap function adds GEMport to ONU map
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001768func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(intfID uint32, onuID uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301769 f.lockCache.Lock()
1770 defer f.lockCache.Unlock()
1771 onugem := f.onuGemInfo[intfID]
1772 // update the gem to the local cache as well as to kv strore
1773 for idx, onu := range onugem {
1774 if onu.OnuID == onuID {
1775 // check if gem already exists , else update the cache and kvstore
1776 for _, gem := range onu.GemPorts {
1777 if gem == gemPort {
1778 log.Debugw("Gem already in cache, no need to update cache and kv store",
1779 log.Fields{"gem": gemPort})
1780 return
1781 }
1782 }
1783 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
1784 f.onuGemInfo[intfID] = onugem
1785 }
1786 }
1787 err := f.resourceMgr.AddGemToOnuGemInfo(intfID, onuID, gemPort)
1788 if err != nil {
1789 log.Errorw("Failed to add gem to onu", log.Fields{"intfId": intfID, "onuId": onuID, "gemPort": gemPort})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001790 return
1791 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001792}
1793
1794// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001795
1796//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
1797func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(serialNumber string, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301798
1799 f.lockCache.Lock()
1800 defer f.lockCache.Unlock()
1801
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001802 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 +05301803 // get onuid from the onugem info cache
1804 onugem := f.onuGemInfo[intfID]
1805 for _, onu := range onugem {
1806 for _, gem := range onu.GemPorts {
1807 if gem == gemPortID {
1808 return onu.OnuID, nil
1809 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001810 }
1811 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001812 log.Errorw("onuid is not found", log.Fields{"serialNumber": serialNumber, "intfId": intfID, "gemPort": gemPortID})
1813 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 -04001814}
1815
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001816//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
1817func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001818 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001819 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001820 var err error
1821
1822 if packetIn.IntfType == "pon" {
1823 // packet indication does not have serial number , so sending as nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001824 if onuID, err = f.getOnuIDfromGemPortMap("", packetIn.IntfId, packetIn.GemportId); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001825 log.Errorw("Unable to get ONU ID from GEM/PON port", log.Fields{"pon port": packetIn.IntfId, "gemport": packetIn.GemportId})
1826 return logicalPortNum, err
1827 }
1828 if packetIn.PortNo != 0 {
1829 logicalPortNum = packetIn.PortNo
1830 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001831 uniID := uint32(0) // FIXME - multi-uni support
1832 logicalPortNum = MkUniPortNum(packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001833 }
1834 // 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 +05301835 f.UpdateGemPortForPktIn(packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001836 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001837 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001838 }
Matteo Scandolo6056e822019-11-13 14:05:29 -08001839 log.Debugw("Retrieved logicalport from packet-in", log.Fields{
1840 "logicalPortNum": logicalPortNum,
1841 "IntfType": packetIn.IntfType,
1842 "packet": hex.EncodeToString(packetIn.Pkt),
1843 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001844 return logicalPortNum, nil
1845}
1846
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001847//GetPacketOutGemPortID returns gemPortId
1848func (f *OpenOltFlowMgr) GetPacketOutGemPortID(intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
1849 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001850 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301851
1852 f.lockCache.Lock()
1853 defer f.lockCache.Unlock()
1854 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum}
1855
1856 gemPortID, ok := f.packetInGemPort[pktInkey]
1857 if ok {
1858 log.Debugw("Found gemport for pktin key", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1859 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001860 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301861 //If gem is not found in cache try to get it from kv store, if found in kv store, update the cache and return.
1862 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(intfID, onuID, portNum)
1863 if err == nil {
1864 if gemPortID != 0 {
1865 f.packetInGemPort[pktInkey] = gemPortID
1866 log.Debugw("Found gem port from kv store and updating cache with gemport",
1867 log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1868 return gemPortID, nil
1869 }
1870 }
1871 log.Errorw("Failed to get gemport", log.Fields{"pktinkey": pktInkey, "gem": gemPortID})
1872 return uint32(0), err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001873}
1874
Manikkaraj kb1d51442019-07-23 10:41:02 -04001875func installFlowOnAllGemports(
1876 f1 func(intfId uint32, onuId uint32, uniId uint32,
1877 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
1878 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32),
1879 f2 func(intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301880 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
1881 classifier map[string]interface{}, action map[string]interface{}),
Manikkaraj kb1d51442019-07-23 10:41:02 -04001882 args map[string]uint32,
1883 classifier map[string]interface{}, action map[string]interface{},
1884 logicalFlow *ofp.OfpFlowStats,
1885 gemPorts []uint32,
1886 FlowType string,
salmansiddiqui7ac62132019-08-22 03:58:50 +00001887 vlanID ...uint32) {
1888 log.Debugw("Installing flow on all GEM ports", log.Fields{"FlowType": FlowType, "gemPorts": gemPorts, "vlan": vlanID})
1889 for _, gemPortID := range gemPorts {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001890 if FlowType == HsiaFlow || FlowType == DhcpFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00001891 f1(args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001892 } else if FlowType == EapolFlow {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301893 f2(args["intfId"], args["onuId"], args["uniId"], args["portNo"], logicalFlow, args["allocId"], gemPortID, vlanID[0], classifier, action)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001894 } else {
1895 log.Errorw("Unrecognized Flow Type", log.Fields{"FlowType": FlowType})
1896 return
1897 }
1898 }
1899}
1900
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001901func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
1902 log.Debug("Adding trap-dhcp-of-nni-flow")
1903 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001904 classifier[PacketTagType] = DoubleTag
1905 action[TrapToHost] = true
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301906 var err error
1907 var networkInterfaceID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001908 /* We manage flowId resource pool on per PON port basis.
1909 Since this situation is tricky, as a hack, we pass the NNI port
1910 index (network_intf_id) as PON port Index for the flowId resource
1911 pool. Also, there is no ONU Id available for trapping DHCP packets
1912 on NNI port, use onu_id as -1 (invalid)
1913 ****************** CAVEAT *******************
1914 This logic works if the NNI Port Id falls within the same valid
1915 range of PON Port Ids. If this doesn't work for some OLT Vendor
1916 we need to have a re-look at this.
1917 *********************************************
1918 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001919 onuID := -1
1920 uniID := -1
1921 gemPortID := -1
1922 allocID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301923 networkInterfaceID, err = getNniIntfID(classifier, action)
1924 if err != nil {
1925 log.Error("Failed to get nniIntf ID")
1926 return
1927 }
1928
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001929 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301930 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001931 log.Debug("Flow-exists--not-re-adding")
1932 return
1933 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301934 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001935 if err != nil {
1936 log.Errorw("Flow id unavailable for DHCP traponNNI flow", log.Fields{"error": err})
1937 return
1938 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001939 var classifierProto *openoltpb2.Classifier
1940 var actionProto *openoltpb2.Action
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001941 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
1942 log.Error("Error in making classifier protobuf for dhcp trap on nni flow")
1943 return
1944 }
1945 log.Debugw("Created classifier proto", log.Fields{"classifier": *classifierProto})
1946 if actionProto = makeOpenOltActionField(action); actionProto == nil {
1947 log.Error("Error in making action protobuf for dhcp trap on nni flow")
1948 return
1949 }
1950 log.Debugw("Created action proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001951 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1952 OnuId: int32(onuID), // OnuId not required
1953 UniId: int32(uniID), // UniId not used
1954 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001955 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001956 AllocId: int32(allocID), // AllocId not used
1957 NetworkIntfId: int32(networkInterfaceID),
1958 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001959 Classifier: classifierProto,
1960 Action: actionProto,
1961 Priority: int32(logicalFlow.Priority),
1962 Cookie: logicalFlow.Cookie,
1963 PortNo: portNo}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001964 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001965 log.Debug("DHCP trap on NNI flow added to device successfully")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301966 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001967 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
1968 int32(onuID),
1969 int32(uniID),
1970 flowID, flowsToKVStore); err != nil {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001971 log.Errorw("Error uploading DHCP DL flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
1972 }
1973 }
1974 return
1975}
salmansiddiqui7ac62132019-08-22 03:58:50 +00001976
Esin Karamanae41e2b2019-12-17 18:13:13 +00001977//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
1978func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
1979 var packetType string
1980 ovid, ivid := false, false
1981 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
1982 vid := vlanID & VlanvIDMask
1983 if vid != ReservedVlan {
1984 ovid = true
1985 }
1986 }
1987 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1988 vid := uint32(metadata)
1989 if vid != ReservedVlan {
1990 ivid = true
1991 }
1992 }
1993 if ovid && ivid {
1994 packetType = DoubleTag
1995 } else if !ovid && !ivid {
1996 packetType = Untagged
1997 } else {
1998 packetType = SingleTag
1999 }
2000 return packetType
2001}
2002
2003//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
2004func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) {
2005 log.Debugw("Adding igmp-trap-of-nni-flow", log.Fields{"classifierInfo": classifier})
2006 action := make(map[string]interface{})
2007 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2008 action[TrapToHost] = true
2009 /* We manage flowId resource pool on per PON port basis.
2010 Since this situation is tricky, as a hack, we pass the NNI port
2011 index (network_intf_id) as PON port Index for the flowId resource
2012 pool. Also, there is no ONU Id available for trapping packets
2013 on NNI port, use onu_id as -1 (invalid)
2014 ****************** CAVEAT *******************
2015 This logic works if the NNI Port Id falls within the same valid
2016 range of PON Port Ids. If this doesn't work for some OLT Vendor
2017 we need to have a re-look at this.
2018 *********************************************
2019 */
2020 onuID := -1
2021 uniID := -1
2022 gemPortID := -1
2023 allocID := -1
2024 networkInterfaceID, err := getNniIntfID(classifier, action)
2025 if err != nil {
2026 log.Error("Failed to get nniIntf ID")
2027 return
2028 }
2029 flowStoreCookie := getFlowStoreCookie(classifier, uint32(0))
2030 if present := f.resourceMgr.IsFlowCookieOnKVStore(uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
2031 log.Debug("igmp-flow-exists--not-re-adding")
2032 return
2033 }
2034 flowID, err := f.resourceMgr.GetFlowID(uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
2035 if err != nil {
2036 log.Errorw("IGMP flow id unavailable for trap-on-NNI flow", log.Fields{"error": err})
2037 return
2038 }
2039 var classifierProto *openoltpb2.Classifier
2040 var actionProto *openoltpb2.Action
2041 if classifierProto = makeOpenOltClassifierField(classifier); classifierProto == nil {
2042 log.Error("Error in making classifier protobuf for igmp trap on nni flow")
2043 return
2044 }
2045 log.Debugw("Created classifier proto for the IGMP flow", log.Fields{"classifier": *classifierProto})
2046 if actionProto = makeOpenOltActionField(action); actionProto == nil {
2047 log.Error("Error in making action protobuf for IGMP trap on nni flow")
2048 return
2049 }
2050 log.Debugw("Created action proto for the IGMP flow", log.Fields{"action": *actionProto})
2051 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2052 OnuId: int32(onuID), // OnuId not required
2053 UniId: int32(uniID), // UniId not used
2054 FlowId: flowID,
2055 FlowType: Downstream,
2056 AllocId: int32(allocID), // AllocId not used
2057 NetworkIntfId: int32(networkInterfaceID),
2058 GemportId: int32(gemPortID), // GemportId not used
2059 Classifier: classifierProto,
2060 Action: actionProto,
2061 Priority: int32(logicalFlow.Priority),
2062 Cookie: logicalFlow.Cookie,
2063 PortNo: portNo}
2064 if ok := f.addFlowToDevice(logicalFlow, &downstreamflow); ok {
2065 log.Debug("IGMP Trap on NNI flow added to device successfully")
2066 flowsToKVStore := f.getUpdatedFlowInfo(&downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
2067 if err := f.updateFlowInfoToKVStore(int32(networkInterfaceID),
2068 int32(onuID),
2069 int32(uniID),
2070 flowID, flowsToKVStore); err != nil {
2071 log.Errorw("Error uploading igmp-trap-on-nni flow into KV store", log.Fields{"flow": downstreamflow, "error": err})
2072 }
2073 }
2074 return
2075}
2076
salmansiddiqui7ac62132019-08-22 03:58:50 +00002077func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2078 if MeterID == 0 { // This should never happen
2079 log.Error("Invalid meter id")
2080 return "", errors.New("invalid meter id")
2081 }
2082 if Dir == tp_pb.Direction_UPSTREAM {
2083 return "upstream", nil
2084 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2085 return "downstream", nil
2086 }
2087 return "", nil
2088}
2089
2090func (f *OpenOltFlowMgr) checkAndAddFlow(args map[string]uint32, classifierInfo map[string]interface{},
Gamze Abakafee36392019-10-03 11:17:24 +00002091 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst *tp.TechProfile, gemPorts []uint32,
2092 TpID uint32, uni string) {
2093 var gemPort uint32
2094 intfID := args[IntfID]
2095 onuID := args[OnuID]
2096 uniID := args[UniID]
2097 portNo := args[PortNo]
2098 allocID := TpInst.UsScheduler.AllocID
salmansiddiqui7ac62132019-08-22 03:58:50 +00002099 if ipProto, ok := classifierInfo[IPProto]; ok {
2100 if ipProto.(uint32) == IPProtoDhcp {
2101 log.Info("Adding DHCP flow")
2102 if pcp, ok := classifierInfo[VlanPcp]; ok {
2103 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2104 tp_pb.Direction_UPSTREAM,
2105 pcp.(uint32))
2106 //Adding DHCP upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00002107 f.addDHCPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002108 } else {
2109 //Adding DHCP upstream flow to all gemports
2110 installFlowOnAllGemports(f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, DhcpFlow)
2111 }
2112
2113 } else if ipProto == IgmpProto {
Esin Karamanae41e2b2019-12-17 18:13:13 +00002114 log.Infow("Adding Us IGMP flow", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "classifierInfo:": classifierInfo})
2115 if pcp, ok := classifierInfo[VlanPcp]; ok {
2116 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2117 tp_pb.Direction_UPSTREAM,
2118 pcp.(uint32))
2119 f.addIGMPTrapFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
2120 } else {
2121 //Adding IGMP upstream flow to all gem ports
2122 installFlowOnAllGemports(f.addIGMPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, IgmpFlow)
2123 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002124 } else {
2125 log.Errorw("Invalid-Classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
2126 return
2127 }
2128 } else if ethType, ok := classifierInfo[EthType]; ok {
2129 if ethType.(uint32) == EapEthType {
2130 log.Info("Adding EAPOL flow")
2131 var vlanID uint32
2132 if val, ok := classifierInfo[VlanVid]; ok {
2133 vlanID = (val.(uint32)) & VlanvIDMask
2134 } else {
2135 vlanID = DefaultMgmtVlan
2136 }
2137 if pcp, ok := classifierInfo[VlanPcp]; ok {
2138 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2139 tp_pb.Direction_UPSTREAM,
2140 pcp.(uint32))
2141
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302142 f.addEAPOLFlow(intfID, onuID, uniID, portNo, flow, allocID, gemPort, vlanID, classifierInfo, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002143 } else {
2144 installFlowOnAllGemports(nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, EapolFlow, vlanID)
2145 }
2146 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002147 } else if _, ok := actionInfo[PushVlan]; ok {
2148 log.Info("Adding upstream data rule")
2149 if pcp, ok := classifierInfo[VlanPcp]; ok {
2150 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
2151 tp_pb.Direction_UPSTREAM,
2152 pcp.(uint32))
2153 //Adding HSIA upstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00002154 f.addUpstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002155 } else {
2156 //Adding HSIA upstream flow to all gemports
2157 installFlowOnAllGemports(f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
2158 }
2159 } else if _, ok := actionInfo[PopVlan]; ok {
2160 log.Info("Adding Downstream data rule")
2161 if pcp, ok := classifierInfo[VlanPcp]; ok {
2162 gemPort = f.techprofile[intfID].GetGemportIDForPbit(TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05002163 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00002164 pcp.(uint32))
2165 //Adding HSIA downstream flow
Gamze Abakafee36392019-10-03 11:17:24 +00002166 f.addDownstreamDataFlow(intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002167 } else {
2168 //Adding HSIA downstream flow to all gemports
2169 installFlowOnAllGemports(f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, HsiaFlow)
2170 }
2171 } else {
2172 log.Errorw("Invalid-flow-type-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo, "flow": flow})
2173 return
2174 }
2175 // Send Techprofile download event to child device in go routine as it takes time
2176 go f.sendTPDownloadMsgToChild(intfID, onuID, uniID, uni, TpID)
2177}
2178
Gamze Abakafee36392019-10-03 11:17:24 +00002179func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
2180 flowIDList := f.flowsUsedByGemPort[gemPK]
2181 if len(flowIDList) > 1 {
2182 return true
2183 }
2184 return false
2185}
2186
Girish Gowdra54934262019-11-13 14:19:55 +05302187func (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 +00002188 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ponIntf, onuID, uniID)
2189 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2190 for _, currentGemPort := range currentGemPorts {
2191 for _, tpGemPort := range tpGemPorts {
2192 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
2193 return true, currentGemPort
2194 }
2195 }
2196 }
Girish Gowdra54934262019-11-13 14:19:55 +05302197 if tpInst.InstanceCtrl.Onu == "single-instance" {
2198 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
2199 f.resourceMgr.RemoveTechProfileIDForOnu(ponIntf, uint32(onuID), uint32(uniID), tpID)
2200 f.DeleteTechProfileInstance(ponIntf, uint32(onuID), uint32(uniID), "", tpID)
2201
2202 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
2203 // still be used on other uni ports.
2204 // So, we need to check and make sure that no other gem port is referring to the given TP ID
2205 // on any other uni port.
2206 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(tpID, ponIntf, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05302207 log.Debugw("got single instance tp instances", log.Fields{"tpInstances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05302208 for i := 0; i < len(tpInstances); i++ {
2209 tpI := tpInstances[i]
2210 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05302211 for _, tpGemPort := range tpGemPorts {
2212 if tpGemPort.GemportID != gemPortID {
2213 log.Debugw("single instance tp is in use by gem", log.Fields{"gemPort": tpGemPort.GemportID})
2214 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05302215 }
2216 }
2217 }
2218 }
Girish Gowdra6b130582019-11-20 16:45:20 +05302219 log.Debug("tech profile is not in use by any gem")
Gamze Abakafee36392019-10-03 11:17:24 +00002220 return false, 0
2221}
2222
salmansiddiqui7ac62132019-08-22 03:58:50 +00002223func formulateClassifierInfoFromFlow(classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002224 for _, field := range flows.GetOfbFields(flow) {
2225 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002226 classifierInfo[EthType] = field.GetEthType()
2227 log.Debug("field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002228 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002229 classifierInfo[IPProto] = field.GetIpProto()
2230 log.Debug("field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002231 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002232 classifierInfo[InPort] = field.GetPort()
2233 log.Debug("field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002234 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05302235 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
salmansiddiqui7ac62132019-08-22 03:58:50 +00002236 log.Debug("field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002237 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002238 classifierInfo[VlanPcp] = field.GetVlanPcp()
2239 log.Debug("field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002240 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002241 classifierInfo[UDPDst] = field.GetUdpDst()
2242 log.Debug("field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002243 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002244 classifierInfo[UDPSrc] = field.GetUdpSrc()
2245 log.Debug("field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002246 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002247 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
2248 log.Debug("field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002249 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002250 classifierInfo[Ipv4Src] = field.GetIpv4Src()
2251 log.Debug("field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002252 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002253 classifierInfo[Metadata] = field.GetTableMetadata()
2254 log.Debug("field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07002255 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002256 classifierInfo[TunnelID] = field.GetTunnelId()
2257 log.Debug("field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
2258 } else {
2259 log.Errorw("Un supported field type", log.Fields{"type": field.Type})
2260 return
2261 }
2262 }
2263}
2264
2265func formulateActionInfoFromFlow(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07002266 for _, action := range flows.GetActions(flow) {
2267 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002268 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002269 actionInfo[Output] = out.GetPort()
2270 log.Debugw("action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002271 } else {
2272 log.Error("Invalid output port in action")
2273 return errors.New("invalid output port in action")
2274 }
Scott Baker355d1742019-10-24 10:57:52 -07002275 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002276 actionInfo[PopVlan] = true
2277 log.Debugw("action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002278 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002279 if out := action.GetPush(); out != nil {
2280 if tpid := out.GetEthertype(); tpid != 0x8100 {
2281 log.Errorw("Invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
2282 } else {
2283 actionInfo[PushVlan] = true
2284 actionInfo[TPID] = tpid
2285 log.Debugw("action-type-push-vlan",
2286 log.Fields{"push_tpid": actionInfo[TPID].(uint32), "in_port": classifierInfo[InPort].(uint32)})
2287 }
2288 }
Scott Baker355d1742019-10-24 10:57:52 -07002289 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002290 if out := action.GetSetField(); out != nil {
2291 if field := out.GetField(); field != nil {
2292 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
2293 log.Errorw("Invalid openflow class", log.Fields{"class": ofClass})
2294 return errors.New("invalid openflow class")
2295 }
2296 /*log.Debugw("action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
2297 if ofbField := field.GetOfbField(); ofbField != nil {
2298 if fieldtype := ofbField.GetType(); fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
2299 if vlan := ofbField.GetVlanVid(); vlan != 0 {
2300 actionInfo[VlanVid] = vlan & 0xfff
2301 log.Debugw("action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
2302 } else {
2303 log.Error("No Invalid vlan id in set vlan-vid action")
2304 }
2305 } else {
2306 log.Errorw("unsupported-action-set-field-type", log.Fields{"type": fieldtype})
2307 }
2308 }
2309 }
2310 }
2311 } else {
2312 log.Errorw("Un supported action type", log.Fields{"type": action.Type})
2313 return errors.New("un supported action type")
2314 }
2315 }
2316 return nil
2317}
2318
2319func formulateControllerBoundTrapFlowInfo(actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002320 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002321 log.Debug("Controller bound trap flows, getting inport from tunnelid")
2322 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2323 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002324 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002325 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07002326 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 +00002327 } else {
2328 log.Error("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
2329 return errors.New("upstream pon-to-controller-flow, NO-inport-in-tunnelid")
2330 }
2331 }
2332 } else {
2333 log.Debug("Non-Controller flows, getting uniport from tunnelid")
2334 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07002335 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002336 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002337 actionInfo[Output] = uniPort
2338 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 +00002339 } else {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002340 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 +00002341 return errors.New("downstream-nni-to-pon-port-flow, no-outport-in-tunnelid")
2342 }
2343 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2344 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002345 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002346 classifierInfo[InPort] = uniPort
David K. Bainbridge82efc492019-09-04 09:57:11 -07002347 log.Debugw("upstream-pon-to-nni-port-flow, inport-in-tunnelid", log.Fields{"newInPort": actionInfo[Output].(uint32),
2348 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002349 } else {
2350 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 -07002351 "outPort": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002352 return errors.New("upstream-pon-to-nni-port-flow, no-inport-in-tunnelid")
2353 }
2354 }
2355 }
2356 return nil
2357}
Gamze Abakafee36392019-10-03 11:17:24 +00002358
Chaitrashree G S90a17952019-11-14 21:51:21 -05002359func getTpIDFromFlow(flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00002360 /* Metadata 8 bytes:
2361 Most Significant 2 Bytes = Inner VLAN
2362 Next 2 Bytes = Tech Profile ID(TPID)
2363 Least Significant 4 Bytes = Port ID
2364 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
2365 subscriber related flows.
2366 */
2367 metadata := flows.GetMetadataFromWriteMetadataAction(flow)
2368 if metadata == 0 {
Chaitrashree G S90a17952019-11-14 21:51:21 -05002369 log.Error("metadata-is-not-present-in-flow-which-is-mandatory")
2370 return 0, errors.New("metadata-is-not-present-in-flow-which-is-mandatory")
Gamze Abakafee36392019-10-03 11:17:24 +00002371 }
2372 TpID := flows.GetTechProfileIDFromWriteMetaData(metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002373 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00002374}
2375
2376func appendUnique(slice []uint32, item uint32) []uint32 {
2377 for _, sliceElement := range slice {
2378 if sliceElement == item {
2379 return slice
2380 }
2381 }
2382 return append(slice, item)
2383}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302384
2385// getNniIntfID gets nni intf id from the flow classifier/action
2386func getNniIntfID(classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
2387
2388 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
2389 if portType == voltha.Port_PON_OLT {
2390 intfID := IntfIDFromNniPortNum(action[Output].(uint32))
2391 log.Debugw("output Nni IntfID is", log.Fields{"intfid": intfID})
2392 return intfID, nil
2393 } else if portType == voltha.Port_ETHERNET_NNI {
2394 intfID := IntfIDFromNniPortNum(classifier[InPort].(uint32))
2395 log.Debugw("input Nni IntfID is", log.Fields{"intfid": intfID})
2396 return intfID, nil
2397 }
2398 return uint32(0), nil
2399}
2400
2401// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
2402func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32) {
2403 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort}
2404
2405 f.lockCache.Lock()
2406 defer f.lockCache.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05002407 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302408 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05002409 if lookupGemPort == gemPort {
2410 log.Debugw("pktin key/value found in cache , no need to update kv as we are assuming both will be in sync",
2411 log.Fields{"pktinkey": pktInkey, "gem": gemPort})
2412 return
2413 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302414 }
Matt Jeanneret1719a072019-12-20 14:50:14 -05002415 f.packetInGemPort[pktInkey] = gemPort
2416
2417 f.resourceMgr.UpdateGemPortForPktIn(pktInkey, gemPort)
2418 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 +05302419 return
2420}
2421
2422// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
2423func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(intfID uint32, onuID uint32, portNum uint32) {
2424
2425 f.lockCache.Lock()
2426 defer f.lockCache.Unlock()
2427 onugem := f.onuGemInfo[intfID]
2428 for idx, onu := range onugem {
2429 if onu.OnuID == onuID {
2430 for _, uni := range onu.UniPorts {
2431 if uni == portNum {
2432 log.Debugw("uni already in cache, no need to update cache and kv store",
2433 log.Fields{"uni": portNum})
2434 return
2435 }
2436 }
2437 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
2438 f.onuGemInfo[intfID] = onugem
2439 }
2440 }
2441 f.resourceMgr.AddUniPortToOnuInfo(intfID, onuID, portNum)
2442}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302443
2444func (f *OpenOltFlowMgr) loadFlowIDlistForGem(intf uint32) {
2445 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(intf)
2446 if err != nil {
2447 log.Error("Failed to get flowid list per gem", log.Fields{"intf": intf})
2448 return
2449 }
2450 for gem, FlowIDs := range flowIDsList {
2451 gemPK := gemPortKey{intf, uint32(gem)}
2452 f.flowsUsedByGemPort[gemPK] = FlowIDs
2453 }
2454 return
2455}