blob: 28d2065246c6d337d7ed508236ea30872ec84cca [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
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
manikkaraj kbf256be2019-03-25 00:13:48 +053019
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"
Girish Gowdracefae192020-03-19 18:14:10 -070025 "errors"
manikkaraj kbf256be2019-03-25 00:13:48 +053026 "fmt"
Manikkaraj kb1d51442019-07-23 10:41:02 -040027 "math/big"
Girish Gowdrafae935c2020-02-17 19:21:44 +053028 "strings"
William Kurkian740a09c2019-10-23 17:07:38 -040029 "sync"
Girish Gowdra3d633032019-12-10 16:37:05 +053030 "time"
Manikkaraj kb1d51442019-07-23 10:41:02 -040031
Esin Karamanccb714b2019-11-29 15:02:06 +000032 "github.com/opencord/voltha-lib-go/v3/pkg/flows"
33 "github.com/opencord/voltha-lib-go/v3/pkg/log"
34 tp "github.com/opencord/voltha-lib-go/v3/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080035 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Esin Karamanccb714b2019-11-29 15:02:06 +000036 "github.com/opencord/voltha-protos/v3/go/common"
37 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
38 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
39 openoltpb2 "github.com/opencord/voltha-protos/v3/go/openolt"
40 tp_pb "github.com/opencord/voltha-protos/v3/go/tech_profile"
41 "github.com/opencord/voltha-protos/v3/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040042
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -040043 //deepcopy "github.com/getlantern/deepcopy"
Girish Gowdra3d633032019-12-10 16:37:05 +053044 "github.com/EagleChen/mapmutex"
Thomas Lee S94109f12020-03-03 16:39:29 +053045 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000046 "google.golang.org/grpc/codes"
47 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053048)
49
50const (
51 // Flow categories
manikkaraj kbf256be2019-03-25 00:13:48 +053052
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070053 //HsiaFlow flow category
54 HsiaFlow = "HSIA_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053055
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070056 //EapolFlow flow category
57 EapolFlow = "EAPOL_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053058
Manikkaraj kb1d51442019-07-23 10:41:02 -040059 //DhcpFlow flow category
60 DhcpFlow = "DHCP_FLOW"
61
Esin Karamanccb714b2019-11-29 15:02:06 +000062 //MulticastFlow flow category
63 MulticastFlow = "MULTICAST_FLOW"
64
Esin Karamanae41e2b2019-12-17 18:13:13 +000065 //IgmpFlow flow category
66 IgmpFlow = "IGMP_FLOW"
67
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070068 //IPProtoDhcp flow category
69 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053070
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070071 //IPProtoIgmp flow category
72 IPProtoIgmp = 2
73
74 //EapEthType eapethtype value
75 EapEthType = 0x888e
76 //LldpEthType lldp ethtype value
77 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000078 //IPv4EthType IPv4 ethernet type value
79 IPv4EthType = 0x800
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070080
81 //IgmpProto proto value
82 IgmpProto = 2
manikkaraj kbf256be2019-03-25 00:13:48 +053083
Andrea Campanella7acc0b92020-02-14 09:20:49 +010084 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
85 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040086
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070087 //DefaultMgmtVlan default vlan value
88 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053089
manikkaraj kbf256be2019-03-25 00:13:48 +053090 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070091
David K. Bainbridge82efc492019-09-04 09:57:11 -070092 //Upstream constant
93 Upstream = "upstream"
94 //Downstream constant
95 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000096 //Multicast constant
97 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070098 //PacketTagType constant
99 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700100 //Untagged constant
101 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700102 //SingleTag constant
103 SingleTag = "single_tag"
104 //DoubleTag constant
105 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +0530106
107 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700108
109 //EthType constant
110 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +0000111 //EthDst constant
112 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700113 //TPID constant
114 TPID = "tpid"
115 //IPProto constant
116 IPProto = "ip_proto"
117 //InPort constant
118 InPort = "in_port"
119 //VlanVid constant
120 VlanVid = "vlan_vid"
121 //VlanPcp constant
122 VlanPcp = "vlan_pcp"
123
124 //UDPDst constant
125 UDPDst = "udp_dst"
126 //UDPSrc constant
127 UDPSrc = "udp_src"
128 //Ipv4Dst constant
129 Ipv4Dst = "ipv4_dst"
130 //Ipv4Src constant
131 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700132 //Metadata constant
133 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700134 //TunnelID constant
135 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700136 //Output constant
137 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000138 //GroupID constant
139 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700140 // Actions
141
142 //PopVlan constant
143 PopVlan = "pop_vlan"
144 //PushVlan constant
145 PushVlan = "push_vlan"
146 //TrapToHost constant
147 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400148 //MaxMeterBand constant
149 MaxMeterBand = 2
150 //VlanPCPMask contant
151 VlanPCPMask = 0xFF
152 //VlanvIDMask constant
153 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000154 //IntfID constant
155 IntfID = "intfId"
156 //OnuID constant
157 OnuID = "onuId"
158 //UniID constant
159 UniID = "uniId"
160 //PortNo constant
161 PortNo = "portNo"
162 //AllocID constant
163 AllocID = "allocId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000164
165 //NoneOnuID constant
166 NoneOnuID = -1
167 //NoneUniID constant
168 NoneUniID = -1
169 //NoneGemPortID constant
170 NoneGemPortID = -1
Girish Gowdrafae935c2020-02-17 19:21:44 +0530171
172 // BinaryStringPrefix is binary string prefix
173 BinaryStringPrefix = "0b"
174 // BinaryBit1 is binary bit 1 expressed as a character
175 BinaryBit1 = '1'
manikkaraj kbf256be2019-03-25 00:13:48 +0530176)
177
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400178type gemPortKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700179 intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400180 gemPort uint32
181}
182
Girish Gowdra3d633032019-12-10 16:37:05 +0530183type pendingFlowDeleteKey struct {
184 intfID uint32
185 onuID uint32
186 uniID uint32
187}
188
189type tpLockKey struct {
190 intfID uint32
191 onuID uint32
192 uniID uint32
193}
194
Gamze Abakafee36392019-10-03 11:17:24 +0000195type schedQueue struct {
196 direction tp_pb.Direction
197 intfID uint32
198 onuID uint32
199 uniID uint32
200 tpID uint32
201 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700202 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000203 meterID uint32
204 flowMetadata *voltha.FlowMetadata
205}
206
Esin Karamanccb714b2019-11-29 15:02:06 +0000207type queueInfoBrief struct {
208 gemPortID uint32
209 servicePriority uint32
210}
211
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700212//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530213type OpenOltFlowMgr struct {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000214 techprofile map[uint32]tp.TechProfileIf
Gamze Abakafee36392019-10-03 11:17:24 +0000215 deviceHandler *DeviceHandler
216 resourceMgr *rsrcMgr.OpenOltResourceMgr
Gamze Abakafee36392019-10-03 11:17:24 +0000217 onuIdsLock sync.RWMutex
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530218 flowsUsedByGemPort map[gemPortKey][]uint32 //gem port id to flow ids
219 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700220 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700221 onuGemInfo map[uint32][]rsrcMgr.OnuGemInfo //onu, gem and uni info local cache, indexed by IntfId
222 // We need to have a global lock on the onuGemInfo map
223 onuGemInfoLock sync.RWMutex
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700224 pendingFlowDelete sync.Map
Girish Gowdra3d633032019-12-10 16:37:05 +0530225 // The mapmutex.Mutex can be fine tuned to use mapmutex.NewCustomizedMapMutex
Esin Karamanccb714b2019-11-29 15:02:06 +0000226 perUserFlowHandleLock *mapmutex.Mutex
227 interfaceToMcastQueueMap map[uint32]*queueInfoBrief /*pon interface -> multicast queue map. Required to assign GEM to a bucket during group population*/
manikkaraj kbf256be2019-03-25 00:13:48 +0530228}
229
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700230//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
npujarec5762e2020-01-01 14:08:48 +0530231func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000232 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530233 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530234 var err error
235 var idx uint32
236
manikkaraj kbf256be2019-03-25 00:13:48 +0530237 flowMgr.deviceHandler = dh
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530238 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000239 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000240 if err = flowMgr.populateTechProfilePerPonPort(ctx); err != nil {
241 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530242 return nil
243 }
William Kurkian740a09c2019-10-23 17:07:38 -0400244 flowMgr.onuIdsLock = sync.RWMutex{}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530245 flowMgr.flowsUsedByGemPort = make(map[gemPortKey][]uint32)
246 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530247 ponPorts := rMgr.DevInfo.GetPonPorts()
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700248 flowMgr.onuGemInfo = make(map[uint32][]rsrcMgr.OnuGemInfo, ponPorts)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530249 //Load the onugem info cache from kv store on flowmanager start
250 for idx = 0; idx < ponPorts; idx++ {
npujarec5762e2020-01-01 14:08:48 +0530251 if flowMgr.onuGemInfo[idx], err = rMgr.GetOnuGemInfo(ctx, idx); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000252 logger.Error(ctx, "failed-to-load-onu-gem-info-cache")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530253 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530254 //Load flowID list per gem map per interface from the kvstore.
npujarec5762e2020-01-01 14:08:48 +0530255 flowMgr.loadFlowIDlistForGem(ctx, idx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530256 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700257 flowMgr.onuGemInfoLock = sync.RWMutex{}
Girish Gowdra3d633032019-12-10 16:37:05 +0530258 flowMgr.pendingFlowDelete = sync.Map{}
Girish Gowdrab77ded92020-04-08 11:45:05 -0700259 flowMgr.perUserFlowHandleLock = mapmutex.NewCustomizedMapMutex(300, 100000000, 10000000, 1.1, 0.2)
Esin Karamanccb714b2019-11-29 15:02:06 +0000260 flowMgr.interfaceToMcastQueueMap = make(map[uint32]*queueInfoBrief)
261 //load interface to multicast queue map from kv store
npujarec5762e2020-01-01 14:08:48 +0530262 flowMgr.loadInterfaceToMulticastQueueMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000263 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530264 return &flowMgr
265}
266
Neha Sharma96b7bf22020-06-15 10:37:32 +0000267func (f *OpenOltFlowMgr) generateStoredFlowID(ctx context.Context, flowID uint32, direction string) (uint64, error) {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700268 if direction == Upstream {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000269 logger.Debugw(ctx, "upstream-flow-shifting-id", log.Fields{"device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700270 return 0x1<<15 | uint64(flowID), nil
David K. Bainbridge82efc492019-09-04 09:57:11 -0700271 } else if direction == Downstream {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000272 logger.Debugw(ctx, "downstream-flow-not-shifting-id", log.Fields{"device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700273 return uint64(flowID), nil
Esin Karamanccb714b2019-11-29 15:02:06 +0000274 } else if direction == Multicast {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000275 logger.Debugw(ctx, "multicast-flow-shifting-id", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000276 return 0x2<<15 | uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400277 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530278 return 0, olterrors.NewErrInvalidValue(log.Fields{"direction": direction}, nil).Log()
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400279 }
280}
281
npujarec5762e2020-01-01 14:08:48 +0530282func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000283 logger.Debugw(ctx, "registering-flow-for-device ",
Shrey Baid26912972020-04-16 21:02:31 +0530284 log.Fields{
285 "flow": flowFromCore,
286 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000287 gemPK := gemPortKey{uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId)}
288 flowIDList, ok := f.flowsUsedByGemPort[gemPK]
289 if !ok {
290 flowIDList = []uint32{deviceFlow.FlowId}
291 }
292 flowIDList = appendUnique(flowIDList, deviceFlow.FlowId)
293 f.flowsUsedByGemPort[gemPK] = flowIDList
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530294 // update the flowids for a gem to the KVstore
npujarec5762e2020-01-01 14:08:48 +0530295 f.resourceMgr.UpdateFlowIDsForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400296}
297
npujarec5762e2020-01-01 14:08:48 +0530298func (f *OpenOltFlowMgr) divideAndAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000299 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
300 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) {
Gamze Abakafee36392019-10-03 11:17:24 +0000301 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530302 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700303 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530304
Neha Sharma96b7bf22020-06-15 10:37:32 +0000305 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530306 "device-id": f.deviceHandler.device.Id,
307 "intf-id": intfID,
308 "onu-id": onuID,
309 "uni-id": uniID,
310 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700311 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530312 "action": actionInfo,
313 "usmeter-iD": UsMeterID,
314 "dsmeter-iD": DsMeterID,
315 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400316 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
317 // is because the flow is an NNI flow and there would be no onu resources associated with it
318 // TODO: properly deal with NNI flows
Manikkaraj kb1d51442019-07-23 10:41:02 -0400319 if onuID <= 0 {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000320 logger.Errorw(ctx, "no-onu-id-for-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530321 log.Fields{
322 "port-no": portNo,
323 "classifer": classifierInfo,
324 "action": actionInfo,
325 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530326 return
327 }
328
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700329 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000330 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530331 "uni": uni,
332 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530333
334 tpLockMapKey := tpLockKey{intfID, onuID, uniID}
335 if f.perUserFlowHandleLock.TryLock(tpLockMapKey) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000336 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530337 "device-id": f.deviceHandler.device.Id,
338 "intf-id": intfID,
339 "onu-id": onuID,
340 "uni-id": uniID,
341 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700342 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530343 "action": actionInfo,
344 "usmeter-id": UsMeterID,
345 "dsmeter-id": DsMeterID,
346 "tp-id": TpID})
npujarec5762e2020-01-01 14:08:48 +0530347 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +0530348 if allocID == 0 || gemPorts == nil || TpInst == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000349 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
Girish Gowdra3d633032019-12-10 16:37:05 +0530350 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
351 return
352 }
353 args := make(map[string]uint32)
354 args[IntfID] = intfID
355 args[OnuID] = onuID
356 args[UniID] = uniID
357 args[PortNo] = portNo
358 args[AllocID] = allocID
359
360 /* Flows can be added specific to gemport if p-bits are received.
361 * If no pbit mentioned then adding flows for all gemports
362 */
npujarec5762e2020-01-01 14:08:48 +0530363 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
Girish Gowdra3d633032019-12-10 16:37:05 +0530364 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
365 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000366 logger.Errorw(ctx, "failed-to-acquire-per-user-flow-handle-lock",
Shrey Baid26912972020-04-16 21:02:31 +0530367 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700368 "intf-id": intfID,
369 "onu-id": onuID,
370 "uni-id": uniID,
371 "flow-id": flow.Id,
372 "flow-cookie": flow.Cookie,
373 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400374 return
375 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530376}
377
salmansiddiqui7ac62132019-08-22 03:58:50 +0000378// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530379func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400380
Neha Sharma96b7bf22020-06-15 10:37:32 +0000381 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530382 log.Fields{"dir": sq.direction,
383 "intf-id": sq.intfID,
384 "onu-id": sq.onuID,
385 "uni-id": sq.uniID,
386 "tp-id": sq.tpID,
387 "meter-id": sq.meterID,
388 "tp-inst": sq.tpInst,
389 "flowmetadata": sq.flowMetadata,
390 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400391
Gamze Abakafee36392019-10-03 11:17:24 +0000392 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000393 if err != nil {
394 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400395 }
396
397 /* Lets make a simple assumption that if the meter-id is present on the KV store,
398 * then the scheduler and queues configuration is applied on the OLT device
399 * in the given direction.
400 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000401
Manikkaraj kb1d51442019-07-23 10:41:02 -0400402 var SchedCfg *tp_pb.SchedulerConfig
npujarec5762e2020-01-01 14:08:48 +0530403 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400404 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530405 return olterrors.NewErrNotFound("meter",
406 log.Fields{"intf-id": sq.intfID,
407 "onu-id": sq.onuID,
408 "uni-id": sq.uniID,
409 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400410 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000411
Manikkaraj kb1d51442019-07-23 10:41:02 -0400412 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000413 if KvStoreMeter.MeterId == sq.meterID {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000414 logger.Debugw(ctx, "scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400415 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400416 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530417 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800418 "unsupported": "meter-id",
419 "kv-store-meter-id": KvStoreMeter.MeterId,
Shrey Baid26912972020-04-16 21:02:31 +0530420 "meter-id-in-flow": sq.meterID,
421 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400422 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000423
Neha Sharma96b7bf22020-06-15 10:37:32 +0000424 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530425 log.Fields{
426 "meter-id": sq.meterID,
427 "direction": Direction,
428 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000429
Gamze Abakafee36392019-10-03 11:17:24 +0000430 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000431 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Gamze Abakafee36392019-10-03 11:17:24 +0000432 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000433 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400434 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000435
436 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530437 return olterrors.NewErrNotFound("scheduler-config",
438 log.Fields{
439 "intf-id": sq.intfID,
440 "direction": sq.direction,
441 "tp-inst": sq.tpInst,
442 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000443 }
444
Manikkaraj kb1d51442019-07-23 10:41:02 -0400445 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000446 if sq.flowMetadata != nil {
447 for _, meter := range sq.flowMetadata.Meters {
448 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400449 meterConfig = meter
Neha Sharma96b7bf22020-06-15 10:37:32 +0000450 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Shrey Baid26912972020-04-16 21:02:31 +0530451 log.Fields{"meterConfig": meterConfig,
452 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400453 break
454 }
455 }
456 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000457 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400458 }
459 if meterConfig == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530460 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800461 "reason": "Could-not-get-meterbands-from-flowMetadata",
462 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530463 "meter-id": sq.meterID,
464 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400465 } else if len(meterConfig.Bands) < MaxMeterBand {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000466 logger.Errorw(ctx, "invalid-number-of-bands-in-meter",
Shrey Baid26912972020-04-16 21:02:31 +0530467 log.Fields{"Bands": meterConfig.Bands,
468 "meter-id": sq.meterID,
469 "device-id": f.deviceHandler.device.Id})
Thomas Lee S94109f12020-03-03 16:39:29 +0530470 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800471 "reason": "Invalid-number-of-bands-in-meter",
472 "meterband-count": len(meterConfig.Bands),
473 "metabands": meterConfig.Bands,
Shrey Baid26912972020-04-16 21:02:31 +0530474 "meter-id": sq.meterID,
475 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400476 }
477 cir := meterConfig.Bands[0].Rate
478 cbs := meterConfig.Bands[0].BurstSize
479 eir := meterConfig.Bands[1].Rate
480 ebs := meterConfig.Bands[1].BurstSize
481 pir := cir + eir
482 pbs := cbs + ebs
483 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
484
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700485 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000486 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400487
npujarec5762e2020-01-01 14:08:48 +0530488 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficShaping, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530489 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
490 log.Fields{"intf-id": sq.intfID,
491 "direction": sq.direction,
492 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400493 }
494
salmansiddiqui7ac62132019-08-22 03:58:50 +0000495 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400496 * store the meter id on the KV store, for further reference.
497 */
npujarec5762e2020-01-01 14:08:48 +0530498 if err := f.resourceMgr.UpdateMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterConfig); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530499 return olterrors.NewErrAdapter("failed-updating-meter-id",
500 log.Fields{"onu-id": sq.onuID,
501 "meter-id": sq.meterID,
502 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400503 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000504 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530505 log.Fields{"direction": Direction,
506 "Meter": meterConfig,
507 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400508 return nil
509}
510
npujarec5762e2020-01-01 14:08:48 +0530511func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficShaping *tp_pb.TrafficShapingInfo, TrafficSched []*tp_pb.TrafficScheduler) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000512 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000513
514 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530515 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
516 log.Fields{"intf-id": sq.intfID,
517 "direction": sq.direction,
518 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000519 }
520
Neha Sharma96b7bf22020-06-15 10:37:32 +0000521 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530522 log.Fields{
523 "direction": sq.direction,
524 "TrafficScheds": TrafficSched,
525 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530526 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000527 IntfId: sq.intfID, OnuId: sq.onuID,
528 UniId: sq.uniID, PortNo: sq.uniPort,
529 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000530 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000531 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000532 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530533 "direction": sq.direction,
534 "traffic-queues": trafficQueues,
535 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000536
537 // On receiving the CreateTrafficQueues request, the driver should create corresponding
538 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000539 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530540 log.Fields{"direction": sq.direction,
541 "traffic-queues": trafficQueues,
542 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530543 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000544 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
545 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000546 TrafficQueues: trafficQueues,
547 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530548 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000549 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000550 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530551 "direction": sq.direction,
552 "traffic-queues": trafficQueues,
553 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000554
Esin Karamanccb714b2019-11-29 15:02:06 +0000555 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000556 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile))
Esin Karamanccb714b2019-11-29 15:02:06 +0000557 if len(multicastTrafficQueues) > 0 {
558 if _, present := f.interfaceToMcastQueueMap[sq.intfID]; !present {
559 //assumed that there is only one queue per PON for the multicast service
560 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
561 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000562 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000563 multicastQueuePerPonPort := multicastTrafficQueues[0]
564 f.interfaceToMcastQueueMap[sq.intfID] = &queueInfoBrief{
565 gemPortID: multicastQueuePerPonPort.GemportId,
566 servicePriority: multicastQueuePerPonPort.Priority,
567 }
568 //also store the queue info in kv store
npujarec5762e2020-01-01 14:08:48 +0530569 f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID,
Esin Karamanccb714b2019-11-29 15:02:06 +0000570 multicastQueuePerPonPort.GemportId,
571 multicastQueuePerPonPort.Priority)
Shrey Baid26912972020-04-16 21:02:31 +0530572
Neha Sharma96b7bf22020-06-15 10:37:32 +0000573 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000574 }
575 }
576 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000577 return nil
578}
579
salmansiddiqui7ac62132019-08-22 03:58:50 +0000580// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530581func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400582
583 var Direction string
584 var SchedCfg *tp_pb.SchedulerConfig
585 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000586 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530587 log.Fields{
588 "direction": sq.direction,
589 "intf-id": sq.intfID,
590 "onu-id": sq.onuID,
591 "uni-id": sq.uniID,
592 "uni-port": sq.uniPort,
593 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000594 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000595 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400596 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000597 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000598 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400599 Direction = "downstream"
600 }
601
Girish Kumar8f73fe02019-12-09 13:19:37 +0000602 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530603 return olterrors.NewErrNotFound("scheduler-config",
604 log.Fields{
605 "int-id": sq.intfID,
606 "direction": sq.direction,
607 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000608 }
609
npujarec5762e2020-01-01 14:08:48 +0530610 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400611 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530612 return olterrors.NewErrNotFound("meter",
613 log.Fields{
614 "onu-id": sq.onuID,
615 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400616 }
617 if KVStoreMeter == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000618 logger.Warnw(ctx, "no-meter-installed-yet",
Shrey Baid26912972020-04-16 21:02:31 +0530619 log.Fields{
620 "direction": Direction,
621 "intf-id": sq.intfID,
622 "onu-id": sq.onuID,
623 "uni-id": sq.uniID,
624 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400625 return nil
626 }
627 cir := KVStoreMeter.Bands[0].Rate
628 cbs := KVStoreMeter.Bands[0].BurstSize
629 eir := KVStoreMeter.Bands[1].Rate
630 ebs := KVStoreMeter.Bands[1].BurstSize
631 pir := cir + eir
632 pbs := cbs + ebs
633
634 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
635
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700636 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000637 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000638
Neha Sharma96b7bf22020-06-15 10:37:32 +0000639 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000640 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530641 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
642 log.Fields{
643 "intf-id": sq.intfID,
644 "direction": sq.direction,
645 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000646 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400647
npujarec5762e2020-01-01 14:08:48 +0530648 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000649 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
650 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000651 TrafficQueues: TrafficQueues,
652 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000653 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530654 log.Fields{
655 "intf-id": sq.intfID,
656 "traffic-queues": TrafficQueues,
657 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400658 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000659 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530660 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000661 IntfId: sq.intfID, OnuId: sq.onuID,
662 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400663 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000664 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530665 log.Fields{
666 "intf-id": sq.intfID,
667 "traffic-schedulers": TrafficSched}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400668 }
669
Neha Sharma96b7bf22020-06-15 10:37:32 +0000670 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000671
672 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400673 * delete the meter id on the KV store.
674 */
npujarec5762e2020-01-01 14:08:48 +0530675 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400676 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530677 return olterrors.NewErrAdapter("unable-to-remove-meter",
678 log.Fields{
679 "onu": sq.onuID,
680 "meter": KVStoreMeter.MeterId,
681 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400682 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000683 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530684 log.Fields{
685 "meter-id": KVStoreMeter.MeterId,
686 "dir": Direction,
687 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400688 return err
689}
690
Gamze Abakafee36392019-10-03 11:17:24 +0000691// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700692func (f *OpenOltFlowMgr) createTcontGemports(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, uniPort uint32, TpID uint32, UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) (uint32, []uint32, interface{}) {
Gamze Abakafee36392019-10-03 11:17:24 +0000693 var allocIDs []uint32
694 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530695 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530696 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000697 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000698
npujarec5762e2020-01-01 14:08:48 +0530699 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
700 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400701
Neha Sharma96b7bf22020-06-15 10:37:32 +0000702 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530703
Neha Sharma96b7bf22020-06-15 10:37:32 +0000704 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530705 "intf-id": intfID,
706 "onu-id": onuID,
707 "uni-id": uniID,
708 "device-id": f.deviceHandler.device.Id,
709 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530710
Manikkaraj kb1d51442019-07-23 10:41:02 -0400711 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530712 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000713 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000714 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530715 log.Fields{
716 "path": tpPath,
717 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530718 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000719 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530720 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000721 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530722 log.Fields{
723 "error": err,
724 "tp-id": TpID,
725 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000726 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530727 }
npujarec5762e2020-01-01 14:08:48 +0530728 f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530729 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000730 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530731 log.Fields{
732 "uni": uni,
733 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530734 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530735 }
Gamze Abakafee36392019-10-03 11:17:24 +0000736
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700737 switch tpInst := techProfileInstance.(type) {
738 case *tp.TechProfile:
739 if UsMeterID != 0 {
740 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
741 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
742 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000743 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700744 log.Fields{
745 "error": err,
746 "meter-id": UsMeterID,
747 "device-id": f.deviceHandler.device.Id})
748 return 0, nil, nil
749 }
750 }
751 if DsMeterID != 0 {
752 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
753 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
754 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000755 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700756 log.Fields{
757 "error": err,
758 "meter-id": DsMeterID,
759 "device-id": f.deviceHandler.device.Id})
760 return 0, nil, nil
761 }
762 }
763 allocID := tpInst.UsScheduler.AllocID
764 for _, gem := range tpInst.UpstreamGemPortAttributeList {
765 gemPortIDs = append(gemPortIDs, gem.GemportID)
766 }
767 allocIDs = appendUnique(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000768
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700769 if tpInstanceExists {
770 return allocID, gemPortIDs, techProfileInstance
771 }
772
773 for _, gemPortID := range gemPortIDs {
774 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
775 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000776 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700777 log.Fields{
778 "alloc-ids": allocIDs,
779 "gemports": allgemPortIDs,
780 "device-id": f.deviceHandler.device.Id})
781 // Send Tconts and GEM ports to KV store
782 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530783 return allocID, gemPortIDs, techProfileInstance
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700784 case *tp.EponProfile:
785 // CreateSchedulerQueues for EPON needs to be implemented here
786 // when voltha-protos for EPON is completed.
787 allocID := tpInst.AllocID
788 for _, gem := range tpInst.UpstreamQueueAttributeList {
789 gemPortIDs = append(gemPortIDs, gem.GemportID)
790 }
791 allocIDs = appendUnique(allocIDs, allocID)
792
793 if tpInstanceExists {
794 return allocID, gemPortIDs, techProfileInstance
795 }
796
797 for _, gemPortID := range gemPortIDs {
798 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
799 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000800 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700801 log.Fields{
802 "alloc-ids": allocIDs,
803 "gemports": allgemPortIDs,
804 "device-id": f.deviceHandler.device.Id})
805 // Send Tconts and GEM ports to KV store
806 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
807 return allocID, gemPortIDs, techProfileInstance
808 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000809 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700810 log.Fields{
811 "tpInst": tpInst})
812 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530813 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530814}
815
npujarec5762e2020-01-01 14:08:48 +0530816func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530817
Neha Sharma96b7bf22020-06-15 10:37:32 +0000818 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530819 log.Fields{
820 "intf-id": intfID,
821 "onu-id": onuID,
822 "uni-id": uniID,
823 "alloc-id": allocID,
824 "gemport-ids": gemPortIDs,
825 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530826 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530827 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000828 logger.Errorw(ctx, "error-while-uploading-allocid-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530829 }
npujarec5762e2020-01-01 14:08:48 +0530830 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000831 logger.Errorw(ctx, "error-while-uploading-gemports-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530832 }
npujarec5762e2020-01-01 14:08:48 +0530833 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000834 logger.Error(ctx, "error-while-uploading-gemtopon-map-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530835 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000836 logger.Infow(ctx, "stored-tconts-and-gem-into-kv-store-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400837 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530838 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400839 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530840}
841
Neha Sharma96b7bf22020-06-15 10:37:32 +0000842func (f *OpenOltFlowMgr) populateTechProfilePerPonPort(ctx context.Context) error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000843 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530844 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000845 for _, intfID := range techRange.IntfIds {
846 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400847 tpCount++
Neha Sharma96b7bf22020-06-15 10:37:32 +0000848 logger.Debugw(ctx, "init-tech-profile-done",
Shrey Baid26912972020-04-16 21:02:31 +0530849 log.Fields{
850 "intf-id": intfID,
851 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530852 }
853 }
854 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400855 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530856 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530857 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800858 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530859 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
860 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530861 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000862 logger.Infow(ctx, "populated-techprofile-for-ponports-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530863 log.Fields{
864 "numofTech": tpCount,
865 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
866 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530867 return nil
868}
869
npujarec5762e2020-01-01 14:08:48 +0530870func (f *OpenOltFlowMgr) addUpstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530871 portNo uint32, uplinkClassifier map[string]interface{},
872 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000873 allocID uint32, gemportID uint32, tpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700874 uplinkClassifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000875 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530876 log.Fields{
877 "uplinkClassifier": uplinkClassifier,
878 "uplinkAction": uplinkAction})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800879 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000880 Upstream, logicalFlow, allocID, gemportID, tpID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530881 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530882}
883
npujarec5762e2020-01-01 14:08:48 +0530884func (f *OpenOltFlowMgr) addDownstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530885 portNo uint32, downlinkClassifier map[string]interface{},
886 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000887 allocID uint32, gemportID uint32, tpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700888 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000889 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530890 log.Fields{
891 "downlinkClassifier": downlinkClassifier,
892 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400893 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
894 if vlan, exists := downlinkClassifier[VlanVid]; exists {
895 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700896 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Neha Sharma96b7bf22020-06-15 10:37:32 +0000897 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, intfID, onuID, uniID) {
898 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530899 log.Fields{
900 "flow": logicalFlow,
901 "device-id": f.deviceHandler.device.Id,
902 "onu-id": onuID,
903 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800904 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400905 }
906 }
907 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530908 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400909
Manikkaraj k884c1242019-04-11 16:26:42 +0530910 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700911 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400912 // vlan_vid is a uint32. must be type asserted as such or conversion fails
913 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530914 if ok {
915 downlinkAction[VlanVid] = dlClVid & 0xfff
916 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530917 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530918 "reason": "failed-to-convert-vlanid-classifier",
919 "vlan-id": VlanVid,
920 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530921 }
922
David K. Bainbridge794735f2020-02-11 21:01:37 -0800923 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000924 Downstream, logicalFlow, allocID, gemportID, tpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530925}
926
npujarec5762e2020-01-01 14:08:48 +0530927func (f *OpenOltFlowMgr) addHSIAFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +0530928 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000929 allocID uint32, gemPortID uint32, tpID uint32) error {
Manikkaraj k884c1242019-04-11 16:26:42 +0530930 /* One of the OLT platform (Broadcom BAL) requires that symmetric
931 flows require the same flow_id to be used across UL and DL.
932 Since HSIA flow is the only symmetric flow currently, we need to
933 re-use the flow_id across both direction. The 'flow_category'
934 takes priority over flow_cookie to find any available HSIA_FLOW
935 id for the ONU.
936 */
Neha Sharma96b7bf22020-06-15 10:37:32 +0000937 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530938 log.Fields{
939 "intf-id": intfID,
940 "onu-id": onuID,
941 "uni-id": uniID,
942 "device-id": f.deviceHandler.device.Id,
943 "classifier": classifier,
944 "action": action,
945 "direction": direction,
946 "alloc-id": allocID,
947 "gemport-id": gemPortID,
948 "logicalflow": *logicalFlow})
Girish Gowdrafae935c2020-02-17 19:21:44 +0530949 var vlanPbit uint32 = 0xff // means no pbit
Gamze Abaka724d0852020-03-18 12:10:24 +0000950 var vlanVid uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400951 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000952 vlanPbit = classifier[VlanPcp].(uint32)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000953 logger.Debugw(ctx, "found-pbit-in-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530954 log.Fields{
955 "vlan-pbit": vlanPbit,
956 "intf-id": intfID,
957 "onu-id": onuID,
958 "device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800959 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000960 logger.Debugw(ctx, "pbit-not-found-in-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530961 log.Fields{
962 "vlan-pcp": VlanPcp,
963 "intf-id": intfID,
964 "onu-id": onuID,
965 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400966 }
Gamze Abaka724d0852020-03-18 12:10:24 +0000967 if _, ok := classifier[VlanVid]; ok {
968 vlanVid = classifier[VlanVid].(uint32)
Shrey Baid26912972020-04-16 21:02:31 +0530969 log.Debugw("found-vlan-in-the-flow",
970 log.Fields{
971 "vlan-vid": vlanVid,
972 "intf-id": intfID,
973 "onu-id": onuID,
974 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +0000975 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000976 flowStoreCookie := getFlowStoreCookie(ctx, classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530977 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000978 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +0530979 log.Fields{
980 "device-id": f.deviceHandler.device.Id,
981 "intf-id": intfID,
982 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800983 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530984 }
Gamze Abaka724d0852020-03-18 12:10:24 +0000985 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanVid, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530986 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530987 return olterrors.NewErrNotFound("hsia-flow-id",
988 log.Fields{
989 "direction": direction,
990 "device-id": f.deviceHandler.device.Id,
991 "intf-id": intfID,
992 "onu-id": onuID,
993 }, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530994 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800995 classifierProto, err := makeOpenOltClassifierField(classifier)
996 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530997 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530998 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000999 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301000 log.Fields{
1001 "classifier": *classifierProto,
1002 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001003 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001004 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301005 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301006 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001007 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301008 log.Fields{
1009 "action": *actionProto,
1010 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001011 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301012 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301013 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001014 log.Fields{
1015 "classifier": classifier,
1016 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301017 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001018 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301019 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001020 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
1021 OnuId: int32(onuID),
1022 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +00001023 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +05301024 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001025 AllocId: int32(allocID),
1026 NetworkIntfId: int32(networkIntfID),
1027 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +05301028 Classifier: classifierProto,
1029 Action: actionProto,
1030 Priority: int32(logicalFlow.Priority),
1031 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001032 PortNo: portNo,
1033 TechProfileId: tpID,
1034 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001035 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301036 return olterrors.NewErrFlowOp("add", flowID, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301037 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001038 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301039 log.Fields{"direction": direction,
1040 "device-id": f.deviceHandler.device.Id,
1041 "flow": flow,
1042 "intf-id": intfID,
1043 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001044 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
1045 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
1046 flow.OnuId,
1047 flow.UniId,
1048 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301049 return olterrors.NewErrPersistence("update", "flow", flowID,
1050 log.Fields{
1051 "flow": flow,
1052 "device-id": f.deviceHandler.device.Id,
1053 "intf-id": intfID,
1054 "onu-id": onuID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001055 }
1056 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301057}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001058
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001059func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1060 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
1061 gemPortID uint32, tpID uint32) error {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301062
Neha Sharma96b7bf22020-06-15 10:37:32 +00001063 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301064 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301065 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001066 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301067 "action": action,
1068 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001069 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301070 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301071
1072 // Clear the action map
1073 for k := range action {
1074 delete(action, k)
1075 }
1076
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001077 action[TrapToHost] = true
1078 classifier[UDPSrc] = uint32(68)
1079 classifier[UDPDst] = uint32(67)
1080 classifier[PacketTagType] = SingleTag
1081 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301082
Neha Sharma96b7bf22020-06-15 10:37:32 +00001083 flowStoreCookie := getFlowStoreCookie(ctx, classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301084 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001085 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301086 log.Fields{
1087 "device-id": f.deviceHandler.device.Id,
1088 "intf-id": intfID,
1089 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001090 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301091 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301092
David K. Bainbridge794735f2020-02-11 21:01:37 -08001093 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, DhcpFlow, 0 /*classifier[VLAN_PCP].(uint32)*/)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301094
1095 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301096 return olterrors.NewErrNotFound("flow",
1097 log.Fields{
1098 "interface-id": intfID,
1099 "gem-port": gemPortID,
1100 "cookie": flowStoreCookie,
1101 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001102 err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301103 }
1104
Neha Sharma96b7bf22020-06-15 10:37:32 +00001105 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301106 log.Fields{
1107 "ul_classifier": classifier,
1108 "ul_action": action,
1109 "uplinkFlowId": flowID,
1110 "intf-id": intfID,
1111 "onu-id": onuID,
1112 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301113
David K. Bainbridge794735f2020-02-11 21:01:37 -08001114 classifierProto, err := makeOpenOltClassifierField(classifier)
1115 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301116 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301117 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001118 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001119 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001120 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301121 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301122 }
1123
David K. Bainbridge794735f2020-02-11 21:01:37 -08001124 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001125 OnuId: int32(onuID),
1126 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301127 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001128 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001129 AllocId: int32(allocID),
1130 NetworkIntfId: int32(networkIntfID),
1131 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301132 Classifier: classifierProto,
1133 Action: actionProto,
1134 Priority: int32(logicalFlow.Priority),
1135 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001136 PortNo: portNo,
1137 TechProfileId: tpID,
1138 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001139 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301140 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001141 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001142 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301143 log.Fields{
1144 "device-id": f.deviceHandler.device.Id,
1145 "flow-id": flowID,
1146 "intf-id": intfID,
1147 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001148 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
1149 if err := f.updateFlowInfoToKVStore(ctx, dhcpFlow.AccessIntfId,
1150 dhcpFlow.OnuId,
1151 dhcpFlow.UniId,
1152 dhcpFlow.FlowId, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301153 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId,
1154 log.Fields{
1155 "flow": dhcpFlow,
1156 "device-id": f.deviceHandler.device.Id}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301157 }
1158
David K. Bainbridge794735f2020-02-11 21:01:37 -08001159 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301160}
1161
Esin Karamanae41e2b2019-12-17 18:13:13 +00001162//addIGMPTrapFlow creates IGMP trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301163func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001164 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, tpID uint32) error {
1165 return f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, IgmpFlow, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001166}
1167
1168//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301169func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001170 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, flowType string, tpID uint32) error {
Esin Karamanae41e2b2019-12-17 18:13:13 +00001171
Neha Sharma96b7bf22020-06-15 10:37:32 +00001172 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001173 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301174 return olterrors.NewErrNotFound("nni-interface-id",
1175 log.Fields{
1176 "classifier": classifier,
1177 "action": action,
1178 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001179 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001180 }
1181
1182 // Clear the action map
1183 for k := range action {
1184 delete(action, k)
1185 }
1186
1187 action[TrapToHost] = true
1188 classifier[PacketTagType] = SingleTag
1189 delete(classifier, VlanVid)
1190
Neha Sharma96b7bf22020-06-15 10:37:32 +00001191 flowStoreCookie := getFlowStoreCookie(ctx, classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301192 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkIntfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001193 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001194 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001195 }
1196
npujarec5762e2020-01-01 14:08:48 +05301197 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, flowType, 0, 0 /*classifier[VLAN_PCP].(uint32)*/)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001198
1199 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301200 return olterrors.NewErrNotFound("flow-id",
1201 log.Fields{
1202 "intf-id": intfID,
1203 "oni-id": onuID,
1204 "cookie": flowStoreCookie,
1205 "flow-type": flowType,
1206 "device-id": f.deviceHandler.device.Id,
1207 "onu-id": onuID},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001208 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001209 }
1210
Neha Sharma96b7bf22020-06-15 10:37:32 +00001211 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301212 log.Fields{
1213 "ul_classifier": classifier,
1214 "ul_action": action,
1215 "uplinkFlowId": flowID,
1216 "flowType": flowType,
1217 "device-id": f.deviceHandler.device.Id,
1218 "intf-id": intfID,
1219 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001220
David K. Bainbridge794735f2020-02-11 21:01:37 -08001221 classifierProto, err := makeOpenOltClassifierField(classifier)
1222 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301223 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001224 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001225 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301226 log.Fields{
1227 "classifier": *classifierProto,
1228 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001229 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001230 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301231 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001232 }
1233
David K. Bainbridge794735f2020-02-11 21:01:37 -08001234 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001235 OnuId: int32(onuID),
1236 UniId: int32(uniID),
1237 FlowId: flowID,
1238 FlowType: Upstream,
1239 AllocId: int32(allocID),
1240 NetworkIntfId: int32(networkIntfID),
1241 GemportId: int32(gemPortID),
1242 Classifier: classifierProto,
1243 Action: actionProto,
1244 Priority: int32(logicalFlow.Priority),
1245 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001246 PortNo: portNo,
1247 TechProfileId: tpID,
1248 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001249
David K. Bainbridge794735f2020-02-11 21:01:37 -08001250 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301251 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": flow, "device-id": f.deviceHandler.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001252 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001253 logger.Infof(ctx, "%s ul-flow-added-to-device-successfully", flowType)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001254
David K. Bainbridge794735f2020-02-11 21:01:37 -08001255 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, flowType, flowID, logicalFlow.Id)
1256 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
1257 flow.OnuId,
1258 flow.UniId,
1259 flow.FlowId, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301260 return olterrors.NewErrPersistence("update", "flow", flow.FlowId, log.Fields{"flow": flow, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001261 }
1262
David K. Bainbridge794735f2020-02-11 21:01:37 -08001263 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001264}
1265
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001266// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001267func (f *OpenOltFlowMgr) addEAPOLFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1268 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
1269 gemPortID uint32, vlanID uint32, tpID uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001270 logger.Infow(ctx, "adding-eapol-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301271 log.Fields{
1272 "intf-id": intfID,
1273 "onu-id": onuID,
1274 "port-no": portNo,
1275 "alloc-id": allocID,
1276 "gemport-id": gemPortID,
1277 "vlan-id": vlanID,
1278 "flow": logicalFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301279
1280 uplinkClassifier := make(map[string]interface{})
1281 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301282
manikkaraj kbf256be2019-03-25 00:13:48 +05301283 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001284 uplinkClassifier[EthType] = uint32(EapEthType)
1285 uplinkClassifier[PacketTagType] = SingleTag
1286 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001287 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301288 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001289 uplinkAction[TrapToHost] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00001290 flowStoreCookie := getFlowStoreCookie(ctx, uplinkClassifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301291 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001292 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301293 "device-id": f.deviceHandler.device.Id,
1294 "onu-id": onuID,
1295 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001296 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301297 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301298 //Add Uplink EAPOL Flow
Gamze Abaka724d0852020-03-18 12:10:24 +00001299 uplinkFlowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0, 0)
manikkaraj kbf256be2019-03-25 00:13:48 +05301300 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301301 return olterrors.NewErrNotFound("flow-id",
1302 log.Fields{
1303 "intf-id": intfID,
1304 "onu-id": onuID,
1305 "coookie": flowStoreCookie,
1306 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001307 err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301308 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001309 logger.Debugw(ctx, "creating-ul-eapol-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301310 log.Fields{
1311 "ul_classifier": uplinkClassifier,
1312 "ul_action": uplinkAction,
1313 "uplinkFlowId": uplinkFlowID,
1314 "device-id": f.deviceHandler.device.Id,
1315 "intf-id": intfID,
1316 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301317
David K. Bainbridge794735f2020-02-11 21:01:37 -08001318 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1319 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301320 return olterrors.NewErrInvalidValue(log.Fields{
1321 "classifier": uplinkClassifier,
1322 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301323 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001324 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301325 log.Fields{
1326 "classifier": *classifierProto,
1327 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001328 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001329 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301330 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301331 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001332 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301333 log.Fields{
1334 "action": *actionProto,
1335 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001336 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301337 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301338 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001339 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301340 "action": action,
1341 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001342 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301343 }
1344
David K. Bainbridge794735f2020-02-11 21:01:37 -08001345 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001346 OnuId: int32(onuID),
1347 UniId: int32(uniID),
1348 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001349 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001350 AllocId: int32(allocID),
1351 NetworkIntfId: int32(networkIntfID),
1352 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301353 Classifier: classifierProto,
1354 Action: actionProto,
1355 Priority: int32(logicalFlow.Priority),
1356 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001357 PortNo: portNo,
1358 TechProfileId: tpID,
1359 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001360 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301361 return olterrors.NewErrFlowOp("add", uplinkFlowID, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001362 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001363 logger.Infow(ctx, "eapol-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301364 log.Fields{
1365 "device-id": f.deviceHandler.device.Id,
1366 "onu-id": onuID,
1367 "intf-id": intfID,
1368 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001369 flowCategory := "EAPOL"
1370 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
1371 if err := f.updateFlowInfoToKVStore(ctx, upstreamFlow.AccessIntfId,
1372 upstreamFlow.OnuId,
1373 upstreamFlow.UniId,
1374 upstreamFlow.FlowId,
1375 /* lowCategory, */
1376 flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301377 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId,
1378 log.Fields{
1379 "flow": upstreamFlow,
1380 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301381 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001382 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301383}
1384
David K. Bainbridge794735f2020-02-11 21:01:37 -08001385func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001386 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001387
1388 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1389 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1390 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001391 if vlanID != ReservedVlan {
1392 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001393 classifier.OVid = vid
1394 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301395 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001396 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1397 vid := uint32(metadata)
1398 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001399 classifier.IVid = vid
1400 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301401 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301402 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001403 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301404 classifier.OPbits = vlanPcp
1405 } else {
1406 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301407 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001408 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1409 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1410 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1411 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001412 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001413 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1414 classifier.PktTagType = pktTagType
1415
1416 switch pktTagType {
1417 case SingleTag:
1418 case DoubleTag:
1419 case Untagged:
1420 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001421 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301422 }
1423 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001424 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301425}
1426
Gamze Abaka724d0852020-03-18 12:10:24 +00001427func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001428 var actionCmd openoltpb2.ActionCmd
1429 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301430 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001431 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301432 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001433 if _, ok := actionInfo[VlanPcp]; ok {
1434 action.Cmd.RemarkInnerPbits = true
1435 action.IPbits = actionInfo[VlanPcp].(uint32)
1436 if _, ok := actionInfo[VlanVid]; ok {
1437 action.Cmd.TranslateInnerTag = true
1438 action.IVid = actionInfo[VlanVid].(uint32)
1439 }
1440 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001441 } else if _, ok := actionInfo[PushVlan]; ok {
1442 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301443 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001444 if _, ok := actionInfo[VlanPcp]; ok {
1445 action.OPbits = actionInfo[VlanPcp].(uint32)
1446 action.Cmd.RemarkOuterPbits = true
1447 if _, ok := classifierInfo[VlanVid]; ok {
1448 action.IVid = classifierInfo[VlanVid].(uint32)
1449 action.Cmd.TranslateInnerTag = true
1450 }
1451 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001452 } else if _, ok := actionInfo[TrapToHost]; ok {
1453 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301454 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001455 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301456 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001457 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301458}
1459
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001460// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001461func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
1462 return f.techprofile[intfID].GetTechProfileInstanceKVPath(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301463}
1464
Gamze Abakafee36392019-10-03 11:17:24 +00001465// DeleteTechProfileInstances removes the tech profile instances from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301466func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, sn string) error {
1467 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001468 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1469
Gamze Abakafee36392019-10-03 11:17:24 +00001470 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301471 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301472 olterrors.NewErrAdapter("delete-tech-profile-failed", log.Fields{"device-id": f.deviceHandler.device.Id}, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301473 // return err
1474 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001475 }
Shrey Baid26912972020-04-16 21:02:31 +05301476 log.Debugw("tech-profile-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001477 }
1478 return nil
1479}
1480
1481// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301482func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001483 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001484 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001485 }
npujarec5762e2020-01-01 14:08:48 +05301486 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301487 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1488 log.Fields{
1489 "tp-id": tpID,
1490 "uni-port-name": uniPortName,
1491 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001492 }
1493 return nil
1494}
1495
Neha Sharma96b7bf22020-06-15 10:37:32 +00001496func getFlowStoreCookie(ctx context.Context, classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +05301497 if len(classifier) == 0 { // should never happen
Neha Sharma96b7bf22020-06-15 10:37:32 +00001498 logger.Error(ctx, "invalid-classfier-object")
manikkaraj kbf256be2019-03-25 00:13:48 +05301499 return 0
1500 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001501 logger.Debugw(ctx, "generating-flow-store-cookie",
Shrey Baid26912972020-04-16 21:02:31 +05301502 log.Fields{
1503 "classifier": classifier,
1504 "gemport-id": gemPortID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301505 var jsonData []byte
1506 var flowString string
1507 var err error
1508 // TODO: Do we need to marshall ??
1509 if jsonData, err = json.Marshal(classifier); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001510 logger.Error(ctx, "failed-to-encode-classifier")
manikkaraj kbf256be2019-03-25 00:13:48 +05301511 return 0
1512 }
1513 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001514 if gemPortID != 0 {
1515 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +05301516 }
1517 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001518 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +05301519 hash := big.NewInt(0)
1520 hash.SetBytes(h.Sum(nil))
Girish Gowdra3d633032019-12-10 16:37:05 +05301521 generatedHash := hash.Uint64()
Neha Sharma96b7bf22020-06-15 10:37:32 +00001522 logger.Debugw(ctx, "hash-generated", log.Fields{"hash": generatedHash})
Girish Gowdra3d633032019-12-10 16:37:05 +05301523 return generatedHash
manikkaraj kbf256be2019-03-25 00:13:48 +05301524}
1525
npujarec5762e2020-01-01 14:08:48 +05301526func (f *OpenOltFlowMgr) getUpdatedFlowInfo(ctx context.Context, flow *openoltpb2.Flow, flowStoreCookie uint64, flowCategory string, deviceFlowID uint32, logicalFlowID uint64) *[]rsrcMgr.FlowInfo {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301527 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001528 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001529 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1530 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1531 */
1532 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001533 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001534 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001535 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001536 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001537 // Get existing flows matching flowid for given subscriber from KV store
npujarec5762e2020-01-01 14:08:48 +05301538 existingFlows := f.resourceMgr.GetFlowIDInfo(ctx, intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001539 if existingFlows != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001540 logger.Debugw(ctx, "flow-exists-for-given-flowID--appending-it-to-current-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301541 log.Fields{
1542 "flow-id": flow.FlowId,
1543 "device-id": f.deviceHandler.device.Id,
1544 "intf-id": intfID,
1545 "onu-id": flow.OnuId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001546 //for _, f := range *existingFlows {
1547 // flows = append(flows, f)
1548 //}
1549 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001550 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001551 logger.Debugw(ctx, "updated-flows-for-given-flowID-and-onuid",
Shrey Baid26912972020-04-16 21:02:31 +05301552 log.Fields{
1553 "updatedflow": flows,
1554 "flow-id": flow.FlowId,
1555 "onu-id": flow.OnuId,
1556 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +05301557 return &flows
1558}
1559
npujarec5762e2020-01-01 14:08:48 +05301560func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(ctx context.Context, intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001561 logger.Debugw(ctx, "storing-flow(s)-into-kv-store", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301562 "flow-id": flowID,
1563 "device-id": f.deviceHandler.device.Id,
1564 "intf-id": intfID,
1565 "onu-id": onuID})
npujarec5762e2020-01-01 14:08:48 +05301566 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, intfID, onuID, uniID, flowID, flows); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001567 logger.Warnw(ctx, "error-while-storing-flow-into-kv-store", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301568 "device-id": f.deviceHandler.device.Id,
1569 "onu-id": onuID,
1570 "intf-id": intfID,
1571 "flow-id": flowID})
manikkaraj k17652a72019-05-06 09:06:36 -04001572 return err
1573 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001574 logger.Infow(ctx, "stored-flow(s)-into-kv-store-successfully!", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301575 "device-id": f.deviceHandler.device.Id,
1576 "onu-id": onuID,
1577 "intf-id": intfID,
1578 "flow-id": flowID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301579 return nil
1580}
1581
David K. Bainbridge794735f2020-02-11 21:01:37 -08001582func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001583
1584 var intfID uint32
1585 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1586 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1587 */
1588 if deviceFlow.AccessIntfId != -1 {
1589 intfID = uint32(deviceFlow.AccessIntfId)
1590 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001591 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001592 intfID = uint32(deviceFlow.NetworkIntfId)
1593 }
1594
Neha Sharma96b7bf22020-06-15 10:37:32 +00001595 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301596 "flow": *deviceFlow,
1597 "device-id": f.deviceHandler.device.Id,
1598 "intf-id": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301599 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001600
1601 st, _ := status.FromError(err)
1602 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001603 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001604 "err": err,
1605 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301606 "device-id": f.deviceHandler.device.Id,
1607 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001608 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301609 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001610
1611 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001612 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301613 log.Fields{"err": err,
1614 "device-flow": deviceFlow,
1615 "device-id": f.deviceHandler.device.Id,
1616 "intf-id": intfID})
npujarec5762e2020-01-01 14:08:48 +05301617 f.resourceMgr.FreeFlowID(ctx, intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001618 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001619 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301620 if deviceFlow.GemportId != -1 {
1621 // No need to register the flow if it is a trap on nni flow.
npujarec5762e2020-01-01 14:08:48 +05301622 f.registerFlow(ctx, logicalFlow, deviceFlow)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301623 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001624 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301625 log.Fields{
1626 "flow": *deviceFlow,
1627 "device-id": f.deviceHandler.device.Id,
1628 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001629 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001630}
1631
Neha Sharma96b7bf22020-06-15 10:37:32 +00001632func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1633 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301634 log.Fields{
1635 "flow": *deviceFlow,
1636 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001637 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1638 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001639 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001640 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301641 log.Fields{
1642 "err": err,
1643 "deviceFlow": deviceFlow,
1644 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001645 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001646 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001647 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001648 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001649
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001650 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001651 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001652 "of-flow-id": ofFlowID,
1653 "flow": *deviceFlow,
1654 "device-id": f.deviceHandler.device.Id,
1655 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001656 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301657}
1658
David K. Bainbridge794735f2020-02-11 21:01:37 -08001659func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001660
1661 classifierInfo := make(map[string]interface{})
1662 actionInfo := make(map[string]interface{})
1663
1664 classifierInfo[EthType] = uint32(LldpEthType)
1665 classifierInfo[PacketTagType] = Untagged
1666 actionInfo[TrapToHost] = true
1667
1668 // LLDP flow is installed to trap LLDP packets on the NNI port.
1669 // We manage flow_id resource pool on per PON port basis.
1670 // Since this situation is tricky, as a hack, we pass the NNI port
1671 // index (network_intf_id) as PON port Index for the flow_id resource
1672 // pool. Also, there is no ONU Id available for trapping LLDP packets
1673 // on NNI port, use onu_id as -1 (invalid)
1674 // ****************** CAVEAT *******************
1675 // This logic works if the NNI Port Id falls within the same valid
1676 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1677 // we need to have a re-look at this.
1678 // *********************************************
1679
1680 var onuID = -1
1681 var uniID = -1
1682 var gemPortID = -1
1683
Neha Sharma96b7bf22020-06-15 10:37:32 +00001684 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001685 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301686 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001687 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001688 var flowStoreCookie = getFlowStoreCookie(ctx, classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05301689 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001690 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001691 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001692 }
npujarec5762e2020-01-01 14:08:48 +05301693 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001694
1695 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301696 return olterrors.NewErrNotFound("flow-id",
1697 log.Fields{
1698 "interface-id": networkInterfaceID,
1699 "onu-id": onuID,
1700 "uni-id": uniID,
1701 "gem-port-id": gemPortID,
1702 "cookie": flowStoreCookie,
1703 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001704 err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001705 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001706 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1707 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301708 return olterrors.NewErrInvalidValue(
1709 log.Fields{
1710 "classifier": classifierInfo,
1711 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001712 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001713 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301714 log.Fields{
1715 "classifier": *classifierProto,
1716 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001717 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001718 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301719 return olterrors.NewErrInvalidValue(
1720 log.Fields{
1721 "action": actionInfo,
1722 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001723 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001724 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301725 log.Fields{
1726 "action": *actionProto,
1727 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001728
1729 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1730 OnuId: int32(onuID), // OnuId not required
1731 UniId: int32(uniID), // UniId not used
1732 FlowId: flowID,
1733 FlowType: Downstream,
1734 NetworkIntfId: int32(networkInterfaceID),
1735 GemportId: int32(gemPortID),
1736 Classifier: classifierProto,
1737 Action: actionProto,
1738 Priority: int32(flow.Priority),
1739 Cookie: flow.Cookie,
1740 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001741 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301742 return olterrors.NewErrFlowOp("add", flowID,
1743 log.Fields{
1744 "flow": downstreamflow,
1745 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001746 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001747 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301748 log.Fields{
1749 "device-id": f.deviceHandler.device.Id,
1750 "onu-id": onuID,
1751 "flow-id": flowID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001752 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, flow.Id)
1753 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
1754 int32(onuID),
1755 int32(uniID),
1756 flowID, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301757 return olterrors.NewErrPersistence("update", "flow", flowID,
1758 log.Fields{
1759 "flow": downstreamflow,
1760 "device-id": f.deviceHandler.device.Id}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001761 }
1762 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301763}
1764
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001765func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1766 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001767}
1768
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001769//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001770func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001771 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1772 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1773 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001774 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301775 log.Fields{
1776 "intf-id": intfID,
1777 "onu-id": onuID,
1778 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001779 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001780 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301781 return nil, olterrors.NewErrNotFound("onu-child-device",
1782 log.Fields{
1783 "onu-id": onuID,
1784 "intf-id": intfID,
1785 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001786 }
1787 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1788 //better to ad the device to cache here.
1789 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1790 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001791 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301792 log.Fields{
1793 "intf-id": intfID,
1794 "onu-id": onuID,
1795 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001796 }
1797
1798 return onuDev.(*OnuDevice), nil
1799}
1800
1801//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001802func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1803 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301804 log.Fields{
1805 "pon-port": intfID,
1806 "onu-id": onuID,
1807 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001808 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001809 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001810 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301811 return nil, olterrors.NewErrNotFound("onu",
1812 log.Fields{
1813 "interface-id": parentPortNo,
1814 "onu-id": onuID,
1815 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001816 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301817 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001818 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301819 log.Fields{
1820 "device-id": f.deviceHandler.device.Id,
1821 "child_device_id": onuDevice.Id,
1822 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301823 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301824}
1825
Neha Sharma96b7bf22020-06-15 10:37:32 +00001826func findNextFlow(ctx context.Context, flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
1827 logger.Info(ctx, "unimplemented-flow %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301828 return nil
1829}
1830
Neha Sharma96b7bf22020-06-15 10:37:32 +00001831func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(ctx context.Context, childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
1832 logger.Info(ctx, "unimplemented-device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301833}
1834
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001835func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001836 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001837 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001838 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001839 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001840}
1841
Neha Sharma96b7bf22020-06-15 10:37:32 +00001842func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1843 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301844 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001845 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301846 log.Fields{
1847 "intf-id": intfID,
1848 "onu-id": onuID,
1849 "uni-id": uniID,
1850 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001851 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301852 }
1853
1854 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001855 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301856 log.Fields{
1857 "msg": *delGemPortMsg,
1858 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301859 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1860 delGemPortMsg,
1861 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301862 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001863 onuDev.deviceType,
1864 onuDev.deviceID,
1865 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301866 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1867 log.Fields{
1868 "from-adapter": f.deviceHandler.device.Type,
1869 "to-adapter": onuDev.deviceType,
1870 "onu-id": onuDev.deviceID,
1871 "proxyDeviceID": onuDev.proxyDeviceID,
1872 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301873 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001874 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301875 log.Fields{
1876 "msg": delGemPortMsg,
1877 "from-adapter": f.deviceHandler.device.Type,
1878 "to-adapter": onuDev.deviceType,
1879 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301880 return nil
1881}
1882
Neha Sharma96b7bf22020-06-15 10:37:32 +00001883func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1884 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301885 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001886 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301887 log.Fields{
1888 "intf-id": intfID,
1889 "onu-id": onuID,
1890 "uni-id": uniID,
1891 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001892 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301893 }
1894
1895 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001896 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301897 log.Fields{
1898 "msg": *delTcontMsg,
1899 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301900 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1901 delTcontMsg,
1902 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301903 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001904 onuDev.deviceType,
1905 onuDev.deviceID,
1906 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301907 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1908 log.Fields{
1909 "from-adapter": f.deviceHandler.device.Type,
1910 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1911 "proxyDeviceID": onuDev.proxyDeviceID,
1912 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301913 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001914 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301915 log.Fields{
1916 "msg": delTcontMsg,
1917 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301918 return nil
1919}
1920
Neha Sharma96b7bf22020-06-15 10:37:32 +00001921func (f *OpenOltFlowMgr) deletePendingFlows(ctx context.Context, Intf uint32, onuID int32, uniID int32) {
Girish Gowdra3d633032019-12-10 16:37:05 +05301922 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1923 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); ok {
1924 if val.(int) > 0 {
1925 pnFlDels := val.(int) - 1
1926 if pnFlDels > 0 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001927 logger.Debugw(ctx, "flow-delete-succeeded--more-pending",
Shrey Baid26912972020-04-16 21:02:31 +05301928 log.Fields{
1929 "intf": Intf,
1930 "onu-id": onuID,
1931 "uni-id": uniID,
1932 "currpendingflowcnt": pnFlDels,
1933 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301934 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1935 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001936 logger.Debugw(ctx, "all-pending-flow-deletes-handled--removing-entry-from-map",
Shrey Baid26912972020-04-16 21:02:31 +05301937 log.Fields{
1938 "intf": Intf,
1939 "onu-id": onuID,
1940 "uni-id": uniID,
1941 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301942 f.pendingFlowDelete.Delete(pnFlDelKey)
1943 }
1944 }
1945 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001946 logger.Debugw(ctx, "no-pending-delete-flows-found",
Shrey Baid26912972020-04-16 21:02:31 +05301947 log.Fields{
1948 "intf": Intf,
1949 "onu-id": onuID,
1950 "uni-id": uniID,
1951 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301952
1953 }
1954
1955}
1956
Girish Gowdrac3037402020-01-22 20:29:53 +05301957// Once the gemport is released for a given onu, it also has to be cleared from local cache
1958// which was used for deriving the gemport->logicalPortNo during packet-in.
1959// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1960// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001961func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001962
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001963 f.onuGemInfoLock.Lock()
1964 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001965
Neha Sharma96b7bf22020-06-15 10:37:32 +00001966 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301967 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001968 "gem-port-id": gemPortID,
1969 "intf-id": intfID,
1970 "onu-id": onuID,
1971 "device-id": f.deviceHandler.device.Id,
1972 "onu-gem": f.onuGemInfo[intfID]})
Girish Gowdrac3037402020-01-22 20:29:53 +05301973 onugem := f.onuGemInfo[intfID]
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001974deleteLoop:
serkant.uluderya96af4932020-02-20 16:58:48 -08001975 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301976 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001977 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301978 // If the gemport is found, delete it from local cache.
1979 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001980 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1981 onugem[i] = onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001982 logger.Infow(ctx, "removed-gemport-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301983 log.Fields{
1984 "intf-id": intfID,
1985 "onu-id": onuID,
1986 "deletedgemport-id": gemPortID,
1987 "gemports": onu.GemPorts,
1988 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001989 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301990 }
1991 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001992 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301993 }
1994 }
1995}
1996
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301997//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001998// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05301999func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302000 gemPortID int32, flowID uint32, flowDirection string,
2001 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002002
Neha Sharma96b7bf22020-06-15 10:37:32 +00002003 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002004 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302005 return olterrors.NewErrNotFound("tp-id",
2006 log.Fields{
2007 "flow": flow,
2008 "intf": Intf,
2009 "onu-id": onuID,
2010 "uni-id": uniID,
2011 "device-id": f.deviceHandler.device.Id}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002012 }
Gamze Abakafee36392019-10-03 11:17:24 +00002013
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002014 if len(updatedFlows) >= 0 {
2015 // There are still flows referencing the same flow_id.
2016 // So the flow should not be freed yet.
2017 // For ex: Case of HSIA where same flow is shared
2018 // between DS and US.
Girish Kumarf26e4882020-03-05 06:49:10 +00002019 if err := f.updateFlowInfoToKVStore(ctx, int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302020 olterrors.NewErrPersistence("update", "flow", flowID,
2021 log.Fields{
2022 "flow": updatedFlows,
2023 "device-id": f.deviceHandler.device.Id}, err).Log()
Girish Kumarf26e4882020-03-05 06:49:10 +00002024 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002025 if len(updatedFlows) == 0 {
Girish Gowdra3d633032019-12-10 16:37:05 +05302026 // Do this for subscriber flows only (not trap from NNI flows)
2027 if onuID != -1 && uniID != -1 {
2028 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
2029 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002030 logger.Debugw(ctx, "creating-entry-for-pending-flow-delete",
Shrey Baid26912972020-04-16 21:02:31 +05302031 log.Fields{
2032 "flow-id": flowID,
2033 "intf": Intf,
2034 "onu-id": onuID,
2035 "uni-id": uniID,
2036 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05302037 f.pendingFlowDelete.Store(pnFlDelKey, 1)
2038 } else {
2039 pnFlDels := val.(int) + 1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002040 logger.Debugw(ctx, "updating-flow-delete-entry",
Shrey Baid26912972020-04-16 21:02:31 +05302041 log.Fields{
2042 "flow-id": flowID,
2043 "intf": Intf,
2044 "onu-id": onuID,
2045 "uni-id": uniID,
2046 "currPendingFlowCnt": pnFlDels,
2047 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05302048 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
2049 }
2050
Neha Sharma96b7bf22020-06-15 10:37:32 +00002051 defer f.deletePendingFlows(ctx, Intf, onuID, uniID)
Girish Gowdra3d633032019-12-10 16:37:05 +05302052 }
2053
Neha Sharma96b7bf22020-06-15 10:37:32 +00002054 logger.Debugw(ctx, "releasing-flow-id-to-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302055 log.Fields{
2056 "Intf": Intf,
2057 "onu-id": onuID,
2058 "uni-id": uniID,
2059 "flow-id": flowID,
2060 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +05302061 f.resourceMgr.FreeFlowID(ctx, Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002062
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002063 uni := getUniPortPath(f.deviceHandler.device.Id, Intf, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002064 tpPath := f.getTPpath(ctx, Intf, uni, tpID)
2065 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
Shrey Baid26912972020-04-16 21:02:31 +05302066 log.Fields{
2067 "TP-PATH": tpPath,
2068 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +05302069 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
Girish Kumarf26e4882020-03-05 06:49:10 +00002070 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
Shrey Baid26912972020-04-16 21:02:31 +05302071 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
2072 log.Fields{
2073 "tp-id": tpID,
2074 "path": tpPath}, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002075 }
2076
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302077 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00002078 if f.isGemPortUsedByAnotherFlow(gemPK) {
2079 flowIDs := f.flowsUsedByGemPort[gemPK]
2080 for i, flowIDinMap := range flowIDs {
2081 if flowIDinMap == flowID {
2082 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302083 // everytime flowsUsedByGemPort cache is updated the same should be updated
2084 // in kv store by calling UpdateFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00002085 f.flowsUsedByGemPort[gemPK] = flowIDs
npujarec5762e2020-01-01 14:08:48 +05302086 f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs)
Gamze Abakafee36392019-10-03 11:17:24 +00002087 break
2088 }
2089 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002090 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
Shrey Baid26912972020-04-16 21:02:31 +05302091 log.Fields{
2092 "gemport-id": gemPortID,
2093 "usedByFlows": flowIDs,
2094 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302095 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00002096 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002097 logger.Debugf(ctx, "gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
npujarec5762e2020-01-01 14:08:48 +05302098 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002099 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
2100 // But it is anyway eventually removed later when the TechProfile is freed, so not a big issue for now.
npujarec5762e2020-01-01 14:08:48 +05302101 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002102 f.deleteGemPortFromLocalCache(ctx, Intf, uint32(onuID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002103 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302104 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
2105 // by calling DeleteFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00002106 delete(f.flowsUsedByGemPort, gemPK)
npujarec5762e2020-01-01 14:08:48 +05302107 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
2108 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002109 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05302110 // Delete the gem port on the ONU.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002111 if err := f.sendDeleteGemPortToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
2112 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302113 log.Fields{
2114 "err": err,
2115 "intf": Intf,
2116 "onu-id": onuID,
2117 "uni-id": uniID,
2118 "device-id": f.deviceHandler.device.Id,
2119 "gemport-id": gemPortID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302120 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002121 switch techprofileInst := techprofileInst.(type) {
2122 case *tp.TechProfile:
2123 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
2124 if !ok {
2125 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID)
2126 f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID)
2127 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
2128 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
2129 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
2130 // Delete the TCONT on the ONU.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002131 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
2132 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002133 log.Fields{
2134 "intf": Intf,
2135 "onu-id": onuID,
2136 "uni-id": uniID,
2137 "device-id": f.deviceHandler.device.Id,
2138 "alloc-id": techprofileInst.UsScheduler.AllocID})
2139 }
2140 }
2141 case *tp.EponProfile:
npujarec5762e2020-01-01 14:08:48 +05302142 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID)
npujarec5762e2020-01-01 14:08:48 +05302143 f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002144 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05302145 // Delete the TCONT on the ONU.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002146 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.AllocID), tpPath); err != nil {
2147 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302148 log.Fields{
2149 "intf": Intf,
2150 "onu-id": onuID,
2151 "uni-id": uniID,
2152 "device-id": f.deviceHandler.device.Id,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002153 "alloc-id": techprofileInst.AllocID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302154 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002155 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002156 logger.Errorw(ctx, "error-unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002157 log.Fields{
2158 "techprofileInst": techprofileInst})
Gamze Abakafee36392019-10-03 11:17:24 +00002159 }
2160 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002161 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302162 return nil
2163}
2164
David K. Bainbridge794735f2020-02-11 21:01:37 -08002165// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302166func (f *OpenOltFlowMgr) clearFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) {
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302167
Neha Sharma96b7bf22020-06-15 10:37:32 +00002168 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302169 log.Fields{
2170 "flowDirection": flowDirection,
2171 "flow": *flow,
2172 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002173
2174 if flowDirection == Multicast {
npujarec5762e2020-01-01 14:08:48 +05302175 f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002176 return
2177 }
2178
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302179 var updatedFlows []rsrcMgr.FlowInfo
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302180 classifierInfo := make(map[string]interface{})
2181
Neha Sharma96b7bf22020-06-15 10:37:32 +00002182 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302183 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002184 logger.Error(ctx, err)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302185 return
2186 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302187
David K. Bainbridge794735f2020-02-11 21:01:37 -08002188 onuID := int32(onu)
2189 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302190
2191 for _, field := range flows.GetOfbFields(flow) {
2192 if field.Type == flows.IP_PROTO {
2193 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002194 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302195 }
2196 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002197 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302198 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002199 "flow-id": flow.Id,
2200 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302201 "onu-id": onuID,
2202 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302203
2204 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2205 onuID = -1
2206 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002207 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
2208 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002209 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002210 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002211 log.Fields{
2212 "port-number": inPort,
2213 "error": err})
2214 return
2215 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302216 }
npujarec5762e2020-01-01 14:08:48 +05302217 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, Intf, onuID, uniID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002218 for _, flowID := range flowIds {
npujarec5762e2020-01-01 14:08:48 +05302219 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flowID)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302220 if flowInfo == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002221 logger.Debugw(ctx, "no-flowinfo-found-in-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302222 log.Fields{
2223 "intf": Intf,
2224 "onu-id": onuID,
2225 "uni-id": uniID,
2226 "flow-id": flowID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302227 return
2228 }
2229 updatedFlows = nil
2230 for _, flow := range *flowInfo {
2231 updatedFlows = append(updatedFlows, flow)
2232 }
2233
2234 for i, storedFlow := range updatedFlows {
2235 if flow.Id == storedFlow.LogicalFlowID {
2236 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002237 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": storedFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002238 // DKB
Neha Sharma96b7bf22020-06-15 10:37:32 +00002239 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2240 logger.Errorw(ctx, "failed-to-remove-flow", log.Fields{"error": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002241 return
2242 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002243 logger.Info(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002244 "flow-id": flow.Id,
2245 "stored-flow": storedFlow,
2246 "device-id": f.deviceHandler.device.Id,
2247 "stored-flow-id": flowID,
2248 "onu-id": onuID,
2249 "intf": Intf,
2250 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08002251 //Remove the Flow from FlowInfo
2252 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
2253 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
2254 flowID, flowDirection, portNum, updatedFlows); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002255 logger.Error(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002256 "flow-id": flow.Id,
2257 "stored-flow": storedFlow,
2258 "device-id": f.deviceHandler.device.Id,
2259 "stored-flow-id": flowID,
2260 "onu-id": onuID,
2261 "intf": Intf,
2262 })
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302263 return
2264 }
2265 }
2266 }
2267 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002268}
2269
Esin Karamanccb714b2019-11-29 15:02:06 +00002270//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
2271// clears resources reserved for this multicast flow
npujarec5762e2020-01-01 14:08:48 +05302272func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) {
Esin Karamanccb714b2019-11-29 15:02:06 +00002273 classifierInfo := make(map[string]interface{})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002274 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
Esin Karaman65409d82020-03-18 10:58:18 +00002275 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002276
2277 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002278 logger.Warnw(ctx, "no-inport-found--cannot-release-resources-of-the-multicast-flow", log.Fields{"flowId:": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002279 return
2280 }
2281
Esin Karamanccb714b2019-11-29 15:02:06 +00002282 var onuID = int32(NoneOnuID)
2283 var uniID = int32(NoneUniID)
2284 var flowID uint32
2285 var updatedFlows []rsrcMgr.FlowInfo
2286
npujarec5762e2020-01-01 14:08:48 +05302287 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, networkInterfaceID, onuID, uniID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002288
2289 for _, flowID = range flowIds {
npujarec5762e2020-01-01 14:08:48 +05302290 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002291 if flowInfo == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002292 logger.Debugw(ctx, "no-multicast-flowinfo-found-in-the-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302293 log.Fields{
2294 "intf": networkInterfaceID,
2295 "onu-id": onuID,
2296 "uni-id": uniID,
2297 "flow-id": flowID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002298 continue
2299 }
2300 updatedFlows = nil
2301 for _, flow := range *flowInfo {
2302 updatedFlows = append(updatedFlows, flow)
2303 }
2304 for i, storedFlow := range updatedFlows {
2305 if flow.Id == storedFlow.LogicalFlowID {
2306 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002307 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302308 log.Fields{
2309 "flow": storedFlow,
2310 "flow-id": flow.Id,
2311 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002312 //remove from device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002313 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002314 // DKB
Neha Sharma96b7bf22020-06-15 10:37:32 +00002315 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002316 log.Fields{
2317 "flow-id": flow.Id,
2318 "error": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00002319 return
2320 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002321 logger.Infow(ctx, "multicast-flow-removed-from-device-successfully", log.Fields{"flow-id": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002322 //Remove the Flow from FlowInfo
2323 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
npujarec5762e2020-01-01 14:08:48 +05302324 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID), NoneOnuID, NoneUniID, flowID, &updatedFlows); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002325 logger.Errorw(ctx, "failed-to-delete-multicast-flow-from-the-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302326 log.Fields{"flow": storedFlow,
2327 "err": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00002328 return
2329 }
2330 //release flow id
Neha Sharma96b7bf22020-06-15 10:37:32 +00002331 logger.Debugw(ctx, "releasing-multicast-flow-id",
Shrey Baid26912972020-04-16 21:02:31 +05302332 log.Fields{"flow-id": flowID,
2333 "interfaceID": networkInterfaceID})
npujarec5762e2020-01-01 14:08:48 +05302334 f.resourceMgr.FreeFlowID(ctx, uint32(networkInterfaceID), NoneOnuID, NoneUniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002335 }
2336 }
2337 }
2338}
2339
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002340//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002341func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002342 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302343 var direction string
2344 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002345
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302346 for _, action := range flows.GetActions(flow) {
2347 if action.Type == flows.OUTPUT {
2348 if out := action.GetOutput(); out != nil {
2349 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002350 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302351 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002352 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002353 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002354 }
2355 }
2356 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002357
2358 if flows.HasGroup(flow) {
2359 direction = Multicast
Girish Gowdracefae192020-03-19 18:14:10 -07002360 f.clearFlowFromResourceManager(ctx, flow, direction)
2361 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002362 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302363 direction = Upstream
2364 } else {
2365 direction = Downstream
2366 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302367
Neha Sharma96b7bf22020-06-15 10:37:32 +00002368 _, intfID, onuID, uniID, _, _, err := FlowExtractInfo(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002369 if err != nil {
2370 return err
2371 }
2372
2373 userKey := tpLockKey{intfID, onuID, uniID}
2374
2375 // Serialize flow removes on a per subscriber basis
2376 if f.perUserFlowHandleLock.TryLock(userKey) {
2377 f.clearFlowFromResourceManager(ctx, flow, direction) //TODO: Take care of the limitations
2378 f.perUserFlowHandleLock.Unlock(userKey)
2379 } else {
2380 // Ideally this should never happen
Neha Sharma96b7bf22020-06-15 10:37:32 +00002381 logger.Errorw(ctx, "failed-to-acquire-lock-to-remove-flow--remove-aborted", log.Fields{"flow": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07002382 return errors.New("failed-to-acquire-per-user-lock")
2383 }
2384
2385 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002386}
2387
Girish Gowdra3d633032019-12-10 16:37:05 +05302388func (f *OpenOltFlowMgr) waitForFlowDeletesToCompleteForOnu(ctx context.Context, intfID uint32, onuID uint32,
2389 uniID uint32, ch chan bool) {
2390 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
2391 for {
2392 select {
2393 case <-time.After(20 * time.Millisecond):
2394 if flowDelRefCnt, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok || flowDelRefCnt == 0 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002395 logger.Debug(ctx, "pending-flow-deletes-completed")
Girish Gowdra3d633032019-12-10 16:37:05 +05302396 ch <- true
2397 return
2398 }
2399 case <-ctx.Done():
Neha Sharma96b7bf22020-06-15 10:37:32 +00002400 logger.Error(ctx, "flow-delete-wait-handler-routine-canceled")
Girish Gowdra3d633032019-12-10 16:37:05 +05302401 return
2402 }
2403 }
2404}
2405
Esin Karamanae41e2b2019-12-17 18:13:13 +00002406//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2407func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2408 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2409 if ethType, ok := classifierInfo[EthType]; ok {
2410 if ethType.(uint32) == IPv4EthType {
2411 if ipProto, ok := classifierInfo[IPProto]; ok {
2412 if ipProto.(uint32) == IgmpProto {
2413 return true
2414 }
2415 }
2416 }
2417 }
2418 }
2419 return false
2420}
2421
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002422// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302423// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002424func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002425 classifierInfo := make(map[string]interface{})
2426 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002427 var UsMeterID uint32
2428 var DsMeterID uint32
2429
Neha Sharma96b7bf22020-06-15 10:37:32 +00002430 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302431 log.Fields{
2432 "flow": flow,
2433 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002434 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002435
Neha Sharma96b7bf22020-06-15 10:37:32 +00002436 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002437 if err != nil {
2438 // Error logging is already done in the called function
2439 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002440 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302441 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002442
Esin Karamanccb714b2019-11-29 15:02:06 +00002443 if flows.HasGroup(flow) {
2444 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002445 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002446 }
2447
manikkaraj k17652a72019-05-06 09:06:36 -04002448 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002449 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002450 if err != nil {
2451 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002452 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002453 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002454
Neha Sharma96b7bf22020-06-15 10:37:32 +00002455 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302456 log.Fields{
2457 "classifierinfo_inport": classifierInfo[InPort],
2458 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002459 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002460
Humera Kouser94d7a842019-08-25 19:04:32 -04002461 if ethType, ok := classifierInfo[EthType]; ok {
2462 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002463 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002464 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002465 }
2466 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002467 if ipProto, ok := classifierInfo[IPProto]; ok {
2468 if ipProto.(uint32) == IPProtoDhcp {
2469 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302470 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002471 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002472 return f.addDHCPTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002473 }
2474 }
2475 }
2476 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002477 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002478 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002479 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002480 }
A R Karthick1f85b802019-10-11 05:06:05 +00002481
Neha Sharma96b7bf22020-06-15 10:37:32 +00002482 f.deviceHandler.AddUniPortToOnu(ctx, intfID, onuID, portNo)
npujarec5762e2020-01-01 14:08:48 +05302483 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002484
Neha Sharma96b7bf22020-06-15 10:37:32 +00002485 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002486 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302487 return olterrors.NewErrNotFound("tpid-for-flow",
2488 log.Fields{
2489 "flow": flow,
2490 "intf-id": IntfID,
2491 "onu-id": onuID,
2492 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002493 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002494 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302495 log.Fields{
2496 "tp-id": TpID,
2497 "intf-id": intfID,
2498 "onu-id": onuID,
2499 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002500 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002501 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002502 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002503 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002504 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002505 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002506
2507 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302508
2509 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
2510 if _, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002511 logger.Debugw(ctx, "no-pending-flows-found--going-ahead-with-flow-install",
Shrey Baid26912972020-04-16 21:02:31 +05302512 log.Fields{
2513 "intf-id": intfID,
2514 "onu-id": onuID,
2515 "uni-id": uniID})
npujarec5762e2020-01-01 14:08:48 +05302516 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05302517 } else {
Girish Gowdra3d633032019-12-10 16:37:05 +05302518 pendingFlowDelComplete := make(chan bool)
2519 go f.waitForFlowDeletesToCompleteForOnu(ctx, intfID, onuID, uniID, pendingFlowDelComplete)
2520 select {
2521 case <-pendingFlowDelComplete:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002522 logger.Debugw(ctx, "all-pending-flow-deletes-completed",
Shrey Baid26912972020-04-16 21:02:31 +05302523 log.Fields{
2524 "intf-id": intfID,
2525 "onu-id": onuID,
2526 "uni-id": uniID})
npujarec5762e2020-01-01 14:08:48 +05302527 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05302528
2529 case <-time.After(10 * time.Second):
Shrey Baid26912972020-04-16 21:02:31 +05302530 return olterrors.NewErrTimeout("pending-flow-deletes",
2531 log.Fields{
2532 "intf-id": intfID,
2533 "onu-id": onuID,
2534 "uni-id": uniID}, nil)
Girish Gowdra3d633032019-12-10 16:37:05 +05302535 }
2536 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002537 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002538}
2539
Esin Karamanccb714b2019-11-29 15:02:06 +00002540// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002541func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002542 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002543 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302544 "classifier-info": classifierInfo,
2545 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002546
Esin Karaman65409d82020-03-18 10:58:18 +00002547 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002548 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002549 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002550 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002551 //this variable acts like a switch. When it is set, multicast flows are classified by eth_dst.
2552 //otherwise, classification is based on ipv4_dst by default.
2553 //the variable can be configurable in the future; it can be read from a configuration path in the kv store.
2554 mcastFlowClassificationByEthDst := false
2555
2556 if mcastFlowClassificationByEthDst {
2557 //replace ipDst with ethDst
2558 if ipv4Dst, ok := classifierInfo[Ipv4Dst]; ok &&
2559 flows.IsMulticastIp(ipv4Dst.(uint32)) {
2560 // replace ipv4_dst classifier with eth_dst
2561 multicastMac := flows.ConvertToMulticastMacBytes(ipv4Dst.(uint32))
2562 delete(classifierInfo, Ipv4Dst)
2563 classifierInfo[EthDst] = multicastMac
Neha Sharma96b7bf22020-06-15 10:37:32 +00002564 logger.Debugw(ctx, "multicast-ip-to-mac-conversion-success",
Shrey Baid26912972020-04-16 21:02:31 +05302565 log.Fields{
2566 "ip:": ipv4Dst.(uint32),
2567 "mac:": multicastMac})
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002568 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002569 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002570 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002571
David K. Bainbridge794735f2020-02-11 21:01:37 -08002572 onuID := NoneOnuID
2573 uniID := NoneUniID
2574 gemPortID := NoneGemPortID
Esin Karamanccb714b2019-11-29 15:02:06 +00002575
Neha Sharma96b7bf22020-06-15 10:37:32 +00002576 flowStoreCookie := getFlowStoreCookie(ctx, classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05302577 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002578 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002579 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002580 }
npujarec5762e2020-01-01 14:08:48 +05302581 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanccb714b2019-11-29 15:02:06 +00002582 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302583 return olterrors.NewErrNotFound("multicast-flow-id",
2584 log.Fields{
2585 "interface-id": networkInterfaceID,
2586 "onu-id": onuID,
2587 "uni-id": uniID,
2588 "gem-port-id": gemPortID,
2589 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00002590 err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002591 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002592 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2593 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002594 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002595 }
2596 groupID := actionInfo[GroupID].(uint32)
2597 multicastFlow := openoltpb2.Flow{
2598 FlowId: flowID,
2599 FlowType: Multicast,
2600 NetworkIntfId: int32(networkInterfaceID),
2601 GroupId: groupID,
2602 Classifier: classifierProto,
2603 Priority: int32(flow.Priority),
2604 Cookie: flow.Cookie}
2605
David K. Bainbridge794735f2020-02-11 21:01:37 -08002606 if err = f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002607 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002608 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002609 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002610 //get cached group
2611 group, _, err := f.GetFlowGroupFromKVStore(ctx, groupID, true)
2612 if err == nil {
2613 //calling groupAdd to set group members after multicast flow creation
Andrea Campanellac63bba92020-03-10 17:01:04 +01002614 if err = f.ModifyGroup(ctx, group); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002615 //cached group can be removed now
2616 f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002617 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002618 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002619 }
2620 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002621
2622 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &multicastFlow, flowStoreCookie, MulticastFlow, flowID, flow.Id)
2623 if err = f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
2624 int32(onuID),
2625 int32(uniID),
2626 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002627 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002628 }
2629 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002630}
2631
Esin Karaman65409d82020-03-18 10:58:18 +00002632//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2633func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2634 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002635 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002636 if err != nil {
2637 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2638 }
2639 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002640 }
Esin Karaman65409d82020-03-18 10:58:18 +00002641 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302642 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002643 if e == nil && len(nniPorts) > 0 {
2644 return nniPorts[0], nil
2645 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302646 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002647}
2648
2649// AddGroup add or update the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002650func (f *OpenOltFlowMgr) AddGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002651 logger.Infow(ctx, "add-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002652 if group == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002653 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002654 }
2655
2656 groupToOlt := openoltpb2.Group{
2657 GroupId: group.Desc.GroupId,
2658 Command: openoltpb2.Group_SET_MEMBERS,
2659 Action: f.buildGroupAction(),
2660 }
2661
Neha Sharma96b7bf22020-06-15 10:37:32 +00002662 logger.Debugw(ctx, "sending-group-to-device", log.Fields{"groupToOlt": groupToOlt})
npujarec5762e2020-01-01 14:08:48 +05302663 _, err := f.deviceHandler.Client.PerformGroupOperation(ctx, &groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002664 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002665 return olterrors.NewErrAdapter("add-group-operation-failed", log.Fields{"groupToOlt": groupToOlt}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002666 }
2667 // group members not created yet. So let's store the group
npujarec5762e2020-01-01 14:08:48 +05302668 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, true); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002669 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002670 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002671 logger.Infow(ctx, "add-group-operation-performed-on-the-device-successfully ", log.Fields{"groupToOlt": groupToOlt})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002672 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002673}
2674
2675//buildGroupAction creates and returns a group action
2676func (f *OpenOltFlowMgr) buildGroupAction() *openoltpb2.Action {
2677 var actionCmd openoltpb2.ActionCmd
2678 var action openoltpb2.Action
2679 action.Cmd = &actionCmd
2680 //pop outer vlan
2681 action.Cmd.RemoveOuterTag = true
2682 return &action
2683}
2684
2685// ModifyGroup updates the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002686func (f *OpenOltFlowMgr) ModifyGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002687 logger.Infow(ctx, "modify-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002688 if group == nil || group.Desc == nil {
Jonathan Hartc4b19112020-04-02 11:21:45 -07002689 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002690 }
2691
Neha Sharma96b7bf22020-06-15 10:37:32 +00002692 newGroup := f.buildGroup(ctx, group.Desc.GroupId, group.Desc.Buckets)
Esin Karamanccb714b2019-11-29 15:02:06 +00002693 //get existing members of the group
npujarec5762e2020-01-01 14:08:48 +05302694 val, groupExists, err := f.GetFlowGroupFromKVStore(ctx, group.Desc.GroupId, false)
Esin Karamanccb714b2019-11-29 15:02:06 +00002695
2696 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002697 return olterrors.NewErrNotFound("flow-group-in-kv-store", log.Fields{"groupId": group.Desc.GroupId}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002698 }
2699
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002700 var current *openoltpb2.Group // represents the group on the device
Esin Karamanccb714b2019-11-29 15:02:06 +00002701 if groupExists {
2702 // group already exists
Neha Sharma96b7bf22020-06-15 10:37:32 +00002703 current = f.buildGroup(ctx, group.Desc.GroupId, val.Desc.GetBuckets())
2704 logger.Debugw(ctx, "modify-group--group exists",
Shrey Baid26912972020-04-16 21:02:31 +05302705 log.Fields{
2706 "group on the device": val,
2707 "new": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002708 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002709 current = f.buildGroup(ctx, group.Desc.GroupId, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002710 }
2711
Neha Sharma96b7bf22020-06-15 10:37:32 +00002712 logger.Debugw(ctx, "modify-group--comparing-current-and-new",
Shrey Baid26912972020-04-16 21:02:31 +05302713 log.Fields{
2714 "group on the device": current,
2715 "new": newGroup})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002716 // get members to be added
Andrea Campanellac63bba92020-03-10 17:01:04 +01002717 membersToBeAdded := f.findDiff(current, newGroup)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002718 // get members to be removed
Andrea Campanellac63bba92020-03-10 17:01:04 +01002719 membersToBeRemoved := f.findDiff(newGroup, current)
Esin Karamanccb714b2019-11-29 15:02:06 +00002720
Neha Sharma96b7bf22020-06-15 10:37:32 +00002721 logger.Infow(ctx, "modify-group--differences found", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302722 "membersToBeAdded": membersToBeAdded,
2723 "membersToBeRemoved": membersToBeRemoved,
2724 "groupId": group.Desc.GroupId})
Esin Karamanccb714b2019-11-29 15:02:06 +00002725
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002726 groupToOlt := openoltpb2.Group{
2727 GroupId: group.Desc.GroupId,
2728 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002729 var errAdd, errRemoved error
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002730 if membersToBeAdded != nil && len(membersToBeAdded) > 0 {
2731 groupToOlt.Command = openoltpb2.Group_ADD_MEMBERS
2732 groupToOlt.Members = membersToBeAdded
2733 //execute addMembers
Neha Sharma96b7bf22020-06-15 10:37:32 +00002734 errAdd = f.callGroupAddRemove(ctx, &groupToOlt)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002735 }
2736 if membersToBeRemoved != nil && len(membersToBeRemoved) > 0 {
2737 groupToOlt.Command = openoltpb2.Group_REMOVE_MEMBERS
2738 groupToOlt.Members = membersToBeRemoved
2739 //execute removeMembers
Neha Sharma96b7bf22020-06-15 10:37:32 +00002740 errRemoved = f.callGroupAddRemove(ctx, &groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002741 }
2742
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002743 //save the modified group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002744 if errAdd == nil && errRemoved == nil {
npujarec5762e2020-01-01 14:08:48 +05302745 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, false); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002746 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002747 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002748 logger.Infow(ctx, "modify-group-was-success--storing-group",
Shrey Baid26912972020-04-16 21:02:31 +05302749 log.Fields{
2750 "group": group,
2751 "existingGroup": current})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002752 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002753 logger.Warnw(ctx, "one-of-the-group-add/remove-operations-failed--cannot-save-group-modifications",
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002754 log.Fields{"group": group})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002755 if errAdd != nil {
2756 return errAdd
2757 }
2758 return errRemoved
Esin Karamanccb714b2019-11-29 15:02:06 +00002759 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002760 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002761}
2762
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002763//callGroupAddRemove performs add/remove buckets operation for the indicated group
Neha Sharma96b7bf22020-06-15 10:37:32 +00002764func (f *OpenOltFlowMgr) callGroupAddRemove(ctx context.Context, group *openoltpb2.Group) error {
2765 if err := f.performGroupOperation(ctx, group); err != nil {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002766 st, _ := status.FromError(err)
2767 //ignore already exists error code
2768 if st.Code() != codes.AlreadyExists {
Andrea Campanellac63bba92020-03-10 17:01:04 +01002769 return olterrors.NewErrGroupOp("groupAddRemove", group.GroupId, log.Fields{"status": st}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002770 }
2771 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002772 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002773}
2774
2775//findDiff compares group members and finds members which only exists in groups2
2776func (f *OpenOltFlowMgr) findDiff(group1 *openoltpb2.Group, group2 *openoltpb2.Group) []*openoltpb2.GroupMember {
2777 var members []*openoltpb2.GroupMember
2778 for _, bucket := range group2.Members {
2779 if !f.contains(group1.Members, bucket) {
2780 // bucket does not exist and must be added
2781 members = append(members, bucket)
2782 }
2783 }
2784 return members
2785}
2786
2787//contains returns true if the members list contains the given member; false otherwise
2788func (f *OpenOltFlowMgr) contains(members []*openoltpb2.GroupMember, member *openoltpb2.GroupMember) bool {
2789 for _, groupMember := range members {
2790 if groupMember.InterfaceId == member.InterfaceId {
2791 return true
2792 }
2793 }
2794 return false
2795}
2796
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002797//performGroupOperation call performGroupOperation operation of openolt proto
Neha Sharma96b7bf22020-06-15 10:37:32 +00002798func (f *OpenOltFlowMgr) performGroupOperation(ctx context.Context, group *openoltpb2.Group) error {
2799 logger.Debugw(ctx, "sending-group-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05302800 log.Fields{
2801 "groupToOlt": group,
2802 "command": group.Command})
Esin Karamanccb714b2019-11-29 15:02:06 +00002803 _, err := f.deviceHandler.Client.PerformGroupOperation(context.Background(), group)
2804 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002805 return olterrors.NewErrAdapter("group-operation-failed", log.Fields{"groupToOlt": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002806 }
Girish Kumarf26e4882020-03-05 06:49:10 +00002807 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002808}
2809
2810//buildGroup build openoltpb2.Group from given group id and bucket list
Neha Sharma96b7bf22020-06-15 10:37:32 +00002811func (f *OpenOltFlowMgr) buildGroup(ctx context.Context, groupID uint32, buckets []*ofp.OfpBucket) *openoltpb2.Group {
Esin Karamanccb714b2019-11-29 15:02:06 +00002812 group := openoltpb2.Group{
2813 GroupId: groupID}
2814 // create members of the group
2815 if buckets != nil {
2816 for _, ofBucket := range buckets {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002817 member := f.buildMember(ctx, ofBucket)
Esin Karamanccb714b2019-11-29 15:02:06 +00002818 if member != nil && !f.contains(group.Members, member) {
2819 group.Members = append(group.Members, member)
2820 }
2821 }
2822 }
2823 return &group
2824}
2825
2826//buildMember builds openoltpb2.GroupMember from an OpenFlow bucket
Neha Sharma96b7bf22020-06-15 10:37:32 +00002827func (f *OpenOltFlowMgr) buildMember(ctx context.Context, ofBucket *ofp.OfpBucket) *openoltpb2.GroupMember {
Esin Karamanccb714b2019-11-29 15:02:06 +00002828 var outPort uint32
2829 outPortFound := false
2830 for _, ofAction := range ofBucket.Actions {
2831 if ofAction.Type == ofp.OfpActionType_OFPAT_OUTPUT {
2832 outPort = ofAction.GetOutput().Port
2833 outPortFound = true
2834 }
2835 }
2836
2837 if !outPortFound {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002838 logger.Debugw(ctx, "bucket-skipped-since-no-out-port-found-in-it", log.Fields{"ofBucket": ofBucket})
Esin Karamanccb714b2019-11-29 15:02:06 +00002839 return nil
2840 }
2841 interfaceID := IntfIDFromUniPortNum(outPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002842 logger.Debugw(ctx, "got-associated-interface-id-of-the-port",
Shrey Baid26912972020-04-16 21:02:31 +05302843 log.Fields{
2844 "portNumber:": outPort,
2845 "interfaceId:": interfaceID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002846 if groupInfo, ok := f.interfaceToMcastQueueMap[interfaceID]; ok {
2847 member := openoltpb2.GroupMember{
2848 InterfaceId: interfaceID,
2849 InterfaceType: openoltpb2.GroupMember_PON,
2850 GemPortId: groupInfo.gemPortID,
2851 Priority: groupInfo.servicePriority,
2852 }
2853 //add member to the group
2854 return &member
2855 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002856 logger.Warnf(ctx, "bucket-skipped-since-interface-2-gem-mapping-cannot-be-found", log.Fields{"ofBucket": ofBucket})
Esin Karamanccb714b2019-11-29 15:02:06 +00002857 return nil
2858}
2859
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002860//sendTPDownloadMsgToChild send payload
Neha Sharma96b7bf22020-06-15 10:37:32 +00002861func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002862
Neha Sharma96b7bf22020-06-15 10:37:32 +00002863 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302864 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002865 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302866 log.Fields{
2867 "intf-id": intfID,
2868 "onu-id": onuID,
2869 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002870 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302871 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002872 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002873
Neha Sharma96b7bf22020-06-15 10:37:32 +00002874 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002875 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002876 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
manikkaraj k17652a72019-05-06 09:06:36 -04002877 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
2878 tpDownloadMsg,
2879 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05302880 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002881 onuDev.deviceType,
2882 onuDev.deviceID,
2883 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002884 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302885 return olterrors.NewErrCommunication("send-techprofile-download-request",
2886 log.Fields{
2887 "from-adapter": f.deviceHandler.device.Type,
2888 "to-adapter": onuDev.deviceType,
2889 "onu-id": onuDev.deviceID,
2890 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002891 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002892 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302893 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302894}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002895
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302896//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002897func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302898
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002899 f.onuGemInfoLock.Lock()
2900 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002901
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302902 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2903 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002904 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002905 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302906 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002907 logger.Infow(ctx, "updated-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302908 log.Fields{
2909 "intf-id": intfID,
2910 "onu-id": onuID,
2911 "serial-num": serialNum,
2912 "onu": onu,
2913 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002914 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002915}
2916
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302917//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302918func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002919
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002920 f.onuGemInfoLock.Lock()
2921 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002922
Neha Sharma96b7bf22020-06-15 10:37:32 +00002923 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302924 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002925 "gem-port-id": gemPort,
2926 "intf-id": intfID,
2927 "onu-id": onuID,
2928 "device-id": f.deviceHandler.device.Id,
2929 "onu-gem": f.onuGemInfo[intfID]})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302930 onugem := f.onuGemInfo[intfID]
2931 // update the gem to the local cache as well as to kv strore
2932 for idx, onu := range onugem {
2933 if onu.OnuID == onuID {
2934 // check if gem already exists , else update the cache and kvstore
2935 for _, gem := range onu.GemPorts {
2936 if gem == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002937 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302938 log.Fields{
2939 "gem": gemPort,
2940 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302941 return
2942 }
2943 }
2944 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
2945 f.onuGemInfo[intfID] = onugem
2946 }
2947 }
npujarec5762e2020-01-01 14:08:48 +05302948 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302949 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002950 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302951 log.Fields{
2952 "intf-id": intfID,
2953 "onu-id": onuID,
2954 "gemPort": gemPort,
2955 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002956 return
2957 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002958 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302959 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002960 "gem-port-id": gemPort,
2961 "intf-id": intfID,
2962 "onu-id": onuID,
2963 "device-id": f.deviceHandler.device.Id,
2964 "onu-gem": f.onuGemInfo[intfID]})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002965}
2966
2967// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002968
2969//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002970func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(ctx context.Context, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302971
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002972 f.onuGemInfoLock.RLock()
2973 defer f.onuGemInfoLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302974
Neha Sharma96b7bf22020-06-15 10:37:32 +00002975 logger.Infow(ctx, "getting-onu-id-from-gem-port-and-pon-port",
Shrey Baid26912972020-04-16 21:02:31 +05302976 log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002977 "device-id": f.deviceHandler.device.Id,
2978 "onu-geminfo": f.onuGemInfo[intfID],
2979 "intf-id": intfID,
2980 "gemport-id": gemPortID})
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002981
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302982 // get onuid from the onugem info cache
2983 onugem := f.onuGemInfo[intfID]
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002984
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302985 for _, onu := range onugem {
2986 for _, gem := range onu.GemPorts {
2987 if gem == gemPortID {
2988 return onu.OnuID, nil
2989 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002990 }
2991 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002992 logger.Errorw(ctx, "onu-id-from-gem-port-not-found", log.Fields{
2993 "gem-port-id": gemPortID,
2994 "interface-id": intfID,
2995 "all-gems-on-port": onu,
2996 })
Thomas Lee S94109f12020-03-03 16:39:29 +05302997 return uint32(0), olterrors.NewErrNotFound("onu-id", log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002998 "interface-id": intfID,
2999 "gem-port-id": gemPortID},
Girish Kumarf26e4882020-03-05 06:49:10 +00003000 nil)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003001}
3002
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003003//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05303004func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003005 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003006 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003007 var err error
3008
3009 if packetIn.IntfType == "pon" {
3010 // packet indication does not have serial number , so sending as nil
Neha Sharma96b7bf22020-06-15 10:37:32 +00003011 if onuID, err = f.getOnuIDfromGemPortMap(ctx, packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003012 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003013 return logicalPortNum, err
3014 }
3015 if packetIn.PortNo != 0 {
3016 logicalPortNum = packetIn.PortNo
3017 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003018 uniID := uint32(0) // FIXME - multi-uni support
Neha Sharma96b7bf22020-06-15 10:37:32 +00003019 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003020 }
3021 // Store the gem port through which the packet_in came. Use the same gem port for packet_out
npujarec5762e2020-01-01 14:08:48 +05303022 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003023 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003024 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003025 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003026 logger.Infow(ctx, "retrieved-logicalport-from-packet-in",
Shrey Baid26912972020-04-16 21:02:31 +05303027 log.Fields{
3028 "logical-port-num": logicalPortNum,
3029 "intf-type": packetIn.IntfType,
3030 "packet": hex.EncodeToString(packetIn.Pkt),
3031 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003032 return logicalPortNum, nil
3033}
3034
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003035//GetPacketOutGemPortID returns gemPortId
npujarec5762e2020-01-01 14:08:48 +05303036func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003037 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003038 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303039
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003040 f.onuGemInfoLock.RLock()
3041 defer f.onuGemInfoLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303042 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003043 var ok bool
3044 gemPortID, ok = f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303045 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003046 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05303047 log.Fields{
3048 "pktinkey": pktInkey,
3049 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003050
3051 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003052 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303053 //If gem is not found in cache try to get it from kv store, if found in kv store, update the cache and return.
npujarec5762e2020-01-01 14:08:48 +05303054 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, intfID, onuID, portNum)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303055 if err == nil {
3056 if gemPortID != 0 {
3057 f.packetInGemPort[pktInkey] = gemPortID
Neha Sharma96b7bf22020-06-15 10:37:32 +00003058 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05303059 log.Fields{
3060 "pktinkey": pktInkey,
3061 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303062 return gemPortID, nil
3063 }
3064 }
Shrey Baid26912972020-04-16 21:02:31 +05303065 return uint32(0), olterrors.NewErrNotFound("gem-port",
3066 log.Fields{
3067 "pktinkey": pktInkey,
3068 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003069
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003070}
3071
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003072// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05303073func installFlowOnAllGemports(ctx context.Context,
3074 f1 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003075 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003076 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, tpID uint32) error,
npujarec5762e2020-01-01 14:08:48 +05303077 f2 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05303078 classifier map[string]interface{}, action map[string]interface{},
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303079 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003080 tpID uint32) error,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003081 args map[string]uint32,
3082 classifier map[string]interface{}, action map[string]interface{},
3083 logicalFlow *ofp.OfpFlowStats,
3084 gemPorts []uint32,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003085 TpInst interface{},
Manikkaraj kb1d51442019-07-23 10:41:02 -04003086 FlowType string,
Gamze Abaka724d0852020-03-18 12:10:24 +00003087 direction string,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003088 tpID uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003089 vlanID ...uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003090 logger.Debugw(ctx, "installing-flow-on-all-gem-ports",
Shrey Baid26912972020-04-16 21:02:31 +05303091 log.Fields{
3092 "FlowType": FlowType,
3093 "gemPorts": gemPorts,
3094 "vlan": vlanID})
Girish Gowdrafae935c2020-02-17 19:21:44 +05303095
Gamze Abaka724d0852020-03-18 12:10:24 +00003096 // The bit mapping for a gemport is expressed in tech-profile as a binary string. For example, 0b00000001
3097 // We need to trim prefix "0b", before further processing
3098 // Once the "0b" prefix is trimmed, we iterate each character in the string to identify which index
3099 // in the string is set to binary bit 1 (expressed as char '1' in the binary string).
3100
3101 // If a particular character in the string is set to '1', identify the index of this character from
3102 // the LSB position which marks the PCP bit consumed by the given gem port.
3103 // This PCP bit now becomes a classifier in the flow.
3104
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003105 switch TpInst := TpInst.(type) {
3106 case *tp.TechProfile:
3107 attributes := TpInst.DownstreamGemPortAttributeList
3108 if direction == Upstream {
3109 attributes = TpInst.UpstreamGemPortAttributeList
Gamze Abaka724d0852020-03-18 12:10:24 +00003110 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003111
3112 for _, gemPortAttribute := range attributes {
3113 if direction == Downstream && strings.ToUpper(gemPortAttribute.IsMulticast) == "TRUE" {
3114 continue
Gamze Abaka724d0852020-03-18 12:10:24 +00003115 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003116 gemPortID := gemPortAttribute.GemportID
3117 if allPbitsMarked(gemPortAttribute.PbitMap) {
3118 classifier[VlanPcp] = uint32(VlanPCPMask)
3119 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3120 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3121 } else if FlowType == EapolFlow {
3122 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3123 }
3124 } else {
3125 for pos, pbitSet := range strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix) {
3126 if pbitSet == BinaryBit1 {
3127 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3128 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3129 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3130 } else if FlowType == EapolFlow {
3131 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3132 }
3133 }
3134 }
3135 }
3136 }
3137 case *tp.EponProfile:
3138 if direction == Upstream {
3139 attributes := TpInst.UpstreamQueueAttributeList
3140 for _, queueAttribute := range attributes {
3141 gemPortID := queueAttribute.GemportID
3142 if allPbitsMarked(queueAttribute.PbitMap) {
3143 classifier[VlanPcp] = uint32(VlanPCPMask)
Gamze Abaka724d0852020-03-18 12:10:24 +00003144 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003145 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
Gamze Abaka724d0852020-03-18 12:10:24 +00003146 } else if FlowType == EapolFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003147 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
Gamze Abaka724d0852020-03-18 12:10:24 +00003148 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003149 } else {
3150 for pos, pbitSet := range strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix) {
3151 if pbitSet == BinaryBit1 {
3152 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3153 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3154 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3155 } else if FlowType == EapolFlow {
3156 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3157 }
3158 }
3159 }
3160 }
3161 }
3162 } else {
3163 attributes := TpInst.DownstreamQueueAttributeList
3164 for _, queueAttribute := range attributes {
3165 gemPortID := queueAttribute.GemportID
3166 if allPbitsMarked(queueAttribute.PbitMap) {
3167 classifier[VlanPcp] = uint32(VlanPCPMask)
3168 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3169 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3170 } else if FlowType == EapolFlow {
3171 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3172 }
3173 } else {
3174 for pos, pbitSet := range strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix) {
3175 if pbitSet == BinaryBit1 {
3176 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3177 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3178 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3179 } else if FlowType == EapolFlow {
3180 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3181 }
3182 }
3183 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05303184 }
3185 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04003186 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003187 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00003188 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpInst": TpInst})
Manikkaraj kb1d51442019-07-23 10:41:02 -04003189 }
3190}
3191
Gamze Abaka724d0852020-03-18 12:10:24 +00003192func allPbitsMarked(pbitMap string) bool {
3193 for pos, pBit := range pbitMap {
3194 if pos >= 2 && pBit != BinaryBit1 {
3195 return false
3196 }
3197 }
3198 return true
3199}
3200
David K. Bainbridge794735f2020-02-11 21:01:37 -08003201func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003202 logger.Debug(ctx, "adding-trap-dhcp-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003203 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003204 classifier[PacketTagType] = DoubleTag
3205 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003206 /* We manage flowId resource pool on per PON port basis.
3207 Since this situation is tricky, as a hack, we pass the NNI port
3208 index (network_intf_id) as PON port Index for the flowId resource
3209 pool. Also, there is no ONU Id available for trapping DHCP packets
3210 on NNI port, use onu_id as -1 (invalid)
3211 ****************** CAVEAT *******************
3212 This logic works if the NNI Port Id falls within the same valid
3213 range of PON Port Ids. If this doesn't work for some OLT Vendor
3214 we need to have a re-look at this.
3215 *********************************************
3216 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003217 onuID := -1
3218 uniID := -1
3219 gemPortID := -1
3220 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00003221 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303222 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303223 return olterrors.NewErrNotFound("nni-intreface-id",
3224 log.Fields{
3225 "classifier": classifier,
3226 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003227 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303228 }
3229
Neha Sharma96b7bf22020-06-15 10:37:32 +00003230 flowStoreCookie := getFlowStoreCookie(ctx, classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303231 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003232 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003233 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003234 }
Gamze Abaka724d0852020-03-18 12:10:24 +00003235 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003236 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303237 return olterrors.NewErrNotFound("dhcp-trap-nni-flow-id",
3238 log.Fields{
3239 "interface-id": networkInterfaceID,
3240 "onu-id": onuID,
3241 "uni-id": uniID,
3242 "gem-port-id": gemPortID,
3243 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003244 err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003245 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003246 classifierProto, err := makeOpenOltClassifierField(classifier)
3247 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003248 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003249 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003250 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003251 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003252 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003253 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003254 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003255 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003256 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3257 OnuId: int32(onuID), // OnuId not required
3258 UniId: int32(uniID), // UniId not used
3259 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07003260 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003261 AllocId: int32(allocID), // AllocId not used
3262 NetworkIntfId: int32(networkInterfaceID),
3263 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003264 Classifier: classifierProto,
3265 Action: actionProto,
3266 Priority: int32(logicalFlow.Priority),
3267 Cookie: logicalFlow.Cookie,
3268 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003269 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003270 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003271 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003272 logger.Info(ctx, "dhcp-trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003273 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3274 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3275 int32(onuID),
3276 int32(uniID),
3277 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003278 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003279 }
3280 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003281}
salmansiddiqui7ac62132019-08-22 03:58:50 +00003282
Esin Karamanae41e2b2019-12-17 18:13:13 +00003283//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
3284func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
3285 var packetType string
3286 ovid, ivid := false, false
3287 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
3288 vid := vlanID & VlanvIDMask
3289 if vid != ReservedVlan {
3290 ovid = true
3291 }
3292 }
3293 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
3294 vid := uint32(metadata)
3295 if vid != ReservedVlan {
3296 ivid = true
3297 }
3298 }
3299 if ovid && ivid {
3300 packetType = DoubleTag
3301 } else if !ovid && !ivid {
3302 packetType = Untagged
3303 } else {
3304 packetType = SingleTag
3305 }
3306 return packetType
3307}
3308
3309//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08003310func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003311 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003312 action := make(map[string]interface{})
3313 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
3314 action[TrapToHost] = true
3315 /* We manage flowId resource pool on per PON port basis.
3316 Since this situation is tricky, as a hack, we pass the NNI port
3317 index (network_intf_id) as PON port Index for the flowId resource
3318 pool. Also, there is no ONU Id available for trapping packets
3319 on NNI port, use onu_id as -1 (invalid)
3320 ****************** CAVEAT *******************
3321 This logic works if the NNI Port Id falls within the same valid
3322 range of PON Port Ids. If this doesn't work for some OLT Vendor
3323 we need to have a re-look at this.
3324 *********************************************
3325 */
3326 onuID := -1
3327 uniID := -1
3328 gemPortID := -1
3329 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00003330 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003331 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303332 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003333 "classifier": classifier,
3334 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003335 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003336 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003337 flowStoreCookie := getFlowStoreCookie(ctx, classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303338 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003339 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003340 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003341 }
npujarec5762e2020-01-01 14:08:48 +05303342 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003343 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303344 return olterrors.NewErrNotFound("igmp-flow-id",
3345 log.Fields{
3346 "interface-id": networkInterfaceID,
3347 "onu-id": onuID,
3348 "uni-id": uniID,
3349 "gem-port-id": gemPortID,
3350 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003351 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003352 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003353 classifierProto, err := makeOpenOltClassifierField(classifier)
3354 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003355 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003356 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003357 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003358 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003359 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003360 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003361 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003362 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003363 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3364 OnuId: int32(onuID), // OnuId not required
3365 UniId: int32(uniID), // UniId not used
3366 FlowId: flowID,
3367 FlowType: Downstream,
3368 AllocId: int32(allocID), // AllocId not used
3369 NetworkIntfId: int32(networkInterfaceID),
3370 GemportId: int32(gemPortID), // GemportId not used
3371 Classifier: classifierProto,
3372 Action: actionProto,
3373 Priority: int32(logicalFlow.Priority),
3374 Cookie: logicalFlow.Cookie,
3375 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003376 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003377 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003378 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003379 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003380 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3381 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3382 int32(onuID),
3383 int32(uniID),
3384 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003385 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003386 }
3387 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003388}
3389
salmansiddiqui7ac62132019-08-22 03:58:50 +00003390func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
3391 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05303392 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003393 }
3394 if Dir == tp_pb.Direction_UPSTREAM {
3395 return "upstream", nil
3396 } else if Dir == tp_pb.Direction_DOWNSTREAM {
3397 return "downstream", nil
3398 }
3399 return "", nil
3400}
3401
npujarec5762e2020-01-01 14:08:48 +05303402func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003403 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003404 tpID uint32, uni string) {
Gamze Abakafee36392019-10-03 11:17:24 +00003405 var gemPort uint32
3406 intfID := args[IntfID]
3407 onuID := args[OnuID]
3408 uniID := args[UniID]
3409 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003410 allocID := args[AllocID]
salmansiddiqui7ac62132019-08-22 03:58:50 +00003411 if ipProto, ok := classifierInfo[IPProto]; ok {
3412 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003413 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003414 "tp-id": tpID,
3415 "alloc-id": allocID,
3416 "intf-id": intfID,
3417 "onu-id": onuID,
3418 "uni-id": uniID,
3419 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003420 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003421 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003422 tp_pb.Direction_UPSTREAM,
3423 pcp.(uint32))
3424 //Adding DHCP upstream flow
Gamze Abaka724d0852020-03-18 12:10:24 +00003425
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003426 f.addDHCPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003427 } else {
3428 //Adding DHCP upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003429 installFlowOnAllGemports(ctx, f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, DhcpFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003430 }
3431
Girish Gowdra32625212020-04-29 11:26:35 -07003432 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003433 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05303434 log.Fields{
3435 "intf-id": intfID,
3436 "onu-id": onuID,
3437 "uni-id": uniID,
3438 "classifier-info:": classifierInfo})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003439 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003440 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
Esin Karamanae41e2b2019-12-17 18:13:13 +00003441 tp_pb.Direction_UPSTREAM,
3442 pcp.(uint32))
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003443 f.addIGMPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003444 } else {
3445 //Adding IGMP upstream flow to all gem ports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003446 installFlowOnAllGemports(ctx, f.addIGMPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, IgmpFlow, Upstream, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003447 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003448 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003449 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003450 return
3451 }
3452 } else if ethType, ok := classifierInfo[EthType]; ok {
3453 if ethType.(uint32) == EapEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003454 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003455 "intf-id": intfID,
3456 "onu-id": onuID,
3457 "uni-id": uniID,
3458 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003459 var vlanID uint32
3460 if val, ok := classifierInfo[VlanVid]; ok {
3461 vlanID = (val.(uint32)) & VlanvIDMask
3462 } else {
3463 vlanID = DefaultMgmtVlan
3464 }
3465 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003466 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003467 tp_pb.Direction_UPSTREAM,
3468 pcp.(uint32))
3469
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003470 f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003471 } else {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003472 installFlowOnAllGemports(ctx, nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, EapolFlow, Upstream, tpID, vlanID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003473 }
3474 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003475 } else if _, ok := actionInfo[PushVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003476 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003477 "intf-id": intfID,
3478 "onu-id": onuID,
3479 "uni-id": uniID,
3480 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003481 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003482 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003483 tp_pb.Direction_UPSTREAM,
3484 pcp.(uint32))
3485 //Adding HSIA upstream flow
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003486 f.addUpstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003487 } else {
3488 //Adding HSIA upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003489 installFlowOnAllGemports(ctx, f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003490 }
3491 } else if _, ok := actionInfo[PopVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003492 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003493 "intf-id": intfID,
3494 "onu-id": onuID,
3495 "uni-id": uniID,
3496 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003497 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003498 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05003499 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003500 pcp.(uint32))
3501 //Adding HSIA downstream flow
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003502 f.addDownstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003503 } else {
3504 //Adding HSIA downstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003505 installFlowOnAllGemports(ctx, f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Downstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003506 }
3507 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003508 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05303509 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003510 "intf-id": intfID,
3511 "onu-id": onuID,
3512 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05303513 "classifier": classifierInfo,
3514 "action": actionInfo,
3515 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003516 return
3517 }
3518 // Send Techprofile download event to child device in go routine as it takes time
Neha Sharma96b7bf22020-06-15 10:37:32 +00003519 go f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003520}
3521
Gamze Abakafee36392019-10-03 11:17:24 +00003522func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
3523 flowIDList := f.flowsUsedByGemPort[gemPK]
3524 if len(flowIDList) > 1 {
3525 return true
3526 }
3527 return false
3528}
3529
npujarec5762e2020-01-01 14:08:48 +05303530func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
3531 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00003532 tpGemPorts := tpInst.UpstreamGemPortAttributeList
3533 for _, currentGemPort := range currentGemPorts {
3534 for _, tpGemPort := range tpGemPorts {
3535 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
3536 return true, currentGemPort
3537 }
3538 }
3539 }
Girish Gowdra54934262019-11-13 14:19:55 +05303540 if tpInst.InstanceCtrl.Onu == "single-instance" {
3541 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
npujarec5762e2020-01-01 14:08:48 +05303542 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, uint32(onuID), uint32(uniID), tpID)
3543 f.DeleteTechProfileInstance(ctx, ponIntf, uint32(onuID), uint32(uniID), "", tpID)
Girish Gowdra54934262019-11-13 14:19:55 +05303544
3545 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
3546 // still be used on other uni ports.
3547 // So, we need to check and make sure that no other gem port is referring to the given TP ID
3548 // on any other uni port.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003549 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID).([]tp.TechProfile)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003550 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303551 for i := 0; i < len(tpInstances); i++ {
3552 tpI := tpInstances[i]
3553 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05303554 for _, tpGemPort := range tpGemPorts {
3555 if tpGemPort.GemportID != gemPortID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003556 logger.Debugw(ctx, "single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05303557 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05303558 }
3559 }
3560 }
3561 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003562 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00003563 return false, 0
3564}
3565
Neha Sharma96b7bf22020-06-15 10:37:32 +00003566func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003567 for _, field := range flows.GetOfbFields(flow) {
3568 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003569 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003570 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003571 } else if field.Type == flows.ETH_DST {
3572 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003573 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003574 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003575 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003576 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003577 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003578 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003579 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003580 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05303581 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003582 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003583 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003584 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003585 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003586 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003587 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003588 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003589 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003590 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003591 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003592 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003593 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003594 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003595 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003596 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003597 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003598 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003599 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003600 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003601 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003602 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003603 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003604 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003605 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003606 return
3607 }
3608 }
3609}
3610
Neha Sharma96b7bf22020-06-15 10:37:32 +00003611func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003612 for _, action := range flows.GetActions(flow) {
3613 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003614 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003615 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003616 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003617 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003618 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003619 }
Scott Baker355d1742019-10-24 10:57:52 -07003620 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003621 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003622 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003623 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003624 if out := action.GetPush(); out != nil {
3625 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003626 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003627 } else {
3628 actionInfo[PushVlan] = true
3629 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003630 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303631 log.Fields{
3632 "push-tpid": actionInfo[TPID].(uint32),
3633 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003634 }
3635 }
Scott Baker355d1742019-10-24 10:57:52 -07003636 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003637 if out := action.GetSetField(); out != nil {
3638 if field := out.GetField(); field != nil {
3639 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003640 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003641 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003642 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3643 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003644 }
3645 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003646 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003647 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003648 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003649 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003650 }
3651 }
3652 return nil
3653}
3654
Neha Sharma96b7bf22020-06-15 10:37:32 +00003655func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003656 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003657 fieldtype := ofbField.GetType()
3658 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003659 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3660 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003661 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003662 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003663 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003664 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003665 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3666 pcp := ofbField.GetVlanPcp()
3667 actionInfo[VlanPcp] = pcp
3668 log.Debugw("action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003669 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003670 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003671 }
3672 }
3673}
3674
Neha Sharma96b7bf22020-06-15 10:37:32 +00003675func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003676 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003677 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003678 } else {
3679 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003680 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003681 }
3682}
3683
Neha Sharma96b7bf22020-06-15 10:37:32 +00003684func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003685 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003686 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003687 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3688 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003689 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003690 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003691 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303692 log.Fields{
3693 "newinport": classifierInfo[InPort].(uint32),
3694 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003695 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303696 return olterrors.NewErrNotFound("child-in-port",
3697 log.Fields{
3698 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3699 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003700 }
3701 }
3702 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003703 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003704 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003705 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003706 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003707 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003708 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303709 log.Fields{
3710 "newoutport": actionInfo[Output].(uint32),
3711 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003712 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303713 return olterrors.NewErrNotFound("out-port",
3714 log.Fields{
3715 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3716 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003717 }
3718 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3719 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003720 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003721 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003722 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303723 log.Fields{
3724 "newinport": actionInfo[Output].(uint32),
3725 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003726 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303727 return olterrors.NewErrNotFound("nni-port",
3728 log.Fields{
3729 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3730 "in-port": classifierInfo[InPort].(uint32),
3731 "out-port": actionInfo[Output].(uint32),
3732 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003733 }
3734 }
3735 }
3736 return nil
3737}
Gamze Abakafee36392019-10-03 11:17:24 +00003738
Neha Sharma96b7bf22020-06-15 10:37:32 +00003739func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003740 /* Metadata 8 bytes:
3741 Most Significant 2 Bytes = Inner VLAN
3742 Next 2 Bytes = Tech Profile ID(TPID)
3743 Least Significant 4 Bytes = Port ID
3744 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3745 subscriber related flows.
3746 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003747 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003748 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003749 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003750 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003751 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003752 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003753}
3754
3755func appendUnique(slice []uint32, item uint32) []uint32 {
3756 for _, sliceElement := range slice {
3757 if sliceElement == item {
3758 return slice
3759 }
3760 }
3761 return append(slice, item)
3762}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303763
3764// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003765func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303766
3767 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3768 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003769 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003770 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003771 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003772 log.Fields{
3773 "port-number": action[Output].(uint32),
3774 "error": err})
3775 return uint32(0), err
3776 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003777 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303778 return intfID, nil
3779 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003780 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003781 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003782 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003783 log.Fields{
3784 "port-number": action[Output].(uint32),
3785 "error": err})
3786 return uint32(0), err
3787 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003788 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303789 return intfID, nil
3790 }
3791 return uint32(0), nil
3792}
3793
3794// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
npujarec5762e2020-01-01 14:08:48 +05303795func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32) {
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003796
3797 f.onuGemInfoLock.Lock()
3798 defer f.onuGemInfoLock.Unlock()
3799
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303800 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort}
Matt Jeanneret1719a072019-12-20 14:50:14 -05003801 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303802 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003803 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003804 logger.Infow(ctx, "pktin-key/value-found-in-cache--no-need-to-update-kv--assume-both-in-sync",
Shrey Baid26912972020-04-16 21:02:31 +05303805 log.Fields{
3806 "pktinkey": pktInkey,
3807 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003808 return
3809 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303810 }
Matt Jeanneret1719a072019-12-20 14:50:14 -05003811 f.packetInGemPort[pktInkey] = gemPort
3812
npujarec5762e2020-01-01 14:08:48 +05303813 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003814 logger.Infow(ctx, "pktin-key-not-found-in-local-cache-value-is-different--updating-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05303815 log.Fields{
3816 "pktinkey": pktInkey,
3817 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303818 return
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003819
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303820}
3821
3822// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303823func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003824
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003825 f.onuGemInfoLock.Lock()
3826 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003827
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303828 onugem := f.onuGemInfo[intfID]
3829 for idx, onu := range onugem {
3830 if onu.OnuID == onuID {
3831 for _, uni := range onu.UniPorts {
3832 if uni == portNum {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003833 logger.Infow(ctx, "uni-already-in-cache--no-need-to-update-cache-and-kv-store", log.Fields{"uni": portNum})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303834 return
3835 }
3836 }
3837 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
3838 f.onuGemInfo[intfID] = onugem
3839 }
3840 }
npujarec5762e2020-01-01 14:08:48 +05303841 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003842
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303843}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303844
npujarec5762e2020-01-01 14:08:48 +05303845func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3846 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303847 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003848 logger.Error(ctx, "failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303849 return
3850 }
3851 for gem, FlowIDs := range flowIDsList {
3852 gemPK := gemPortKey{intf, uint32(gem)}
3853 f.flowsUsedByGemPort[gemPK] = FlowIDs
3854 }
3855 return
3856}
Esin Karamanccb714b2019-11-29 15:02:06 +00003857
3858//loadInterfaceToMulticastQueueMap reads multicast queues per interface from the KV store
3859//and put them into interfaceToMcastQueueMap.
npujarec5762e2020-01-01 14:08:48 +05303860func (f *OpenOltFlowMgr) loadInterfaceToMulticastQueueMap(ctx context.Context) {
3861 storedMulticastQueueMap, err := f.resourceMgr.GetMcastQueuePerInterfaceMap(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00003862 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003863 logger.Error(ctx, "failed-to-get-pon-interface-to-multicast-queue-map")
Esin Karamanccb714b2019-11-29 15:02:06 +00003864 return
3865 }
3866 for intf, queueInfo := range storedMulticastQueueMap {
3867 q := queueInfoBrief{
3868 gemPortID: queueInfo[0],
3869 servicePriority: queueInfo[1],
3870 }
3871 f.interfaceToMcastQueueMap[intf] = &q
3872 }
3873}
3874
3875//GetFlowGroupFromKVStore fetches and returns flow group from the KV store. Returns (nil, false, error) if any problem occurs during
3876//fetching the data. Returns (group, true, nil) if the group is fetched and returned successfully.
3877//Returns (nil, false, nil) if the group does not exists in the KV store.
npujarec5762e2020-01-01 14:08:48 +05303878func (f *OpenOltFlowMgr) GetFlowGroupFromKVStore(ctx context.Context, groupID uint32, cached bool) (*ofp.OfpGroupEntry, bool, error) {
3879 exists, groupInfo, err := f.resourceMgr.GetFlowGroupFromKVStore(ctx, groupID, cached)
Esin Karamanccb714b2019-11-29 15:02:06 +00003880 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003881 return nil, false, olterrors.NewErrNotFound("flow-group", log.Fields{"group-id": groupID}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00003882 }
3883 if exists {
3884 return newGroup(groupInfo.GroupID, groupInfo.OutPorts), exists, nil
3885 }
3886 return nil, exists, nil
3887}
3888
3889func newGroup(groupID uint32, outPorts []uint32) *ofp.OfpGroupEntry {
3890 groupDesc := ofp.OfpGroupDesc{
3891 Type: ofp.OfpGroupType_OFPGT_ALL,
3892 GroupId: groupID,
3893 }
3894 groupEntry := ofp.OfpGroupEntry{
3895 Desc: &groupDesc,
3896 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003897 for i := 0; i < len(outPorts); i++ {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003898 var acts []*ofp.OfpAction
Esin Karamanccb714b2019-11-29 15:02:06 +00003899 acts = append(acts, flows.Output(outPorts[i]))
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003900 bucket := ofp.OfpBucket{
3901 Actions: acts,
3902 }
3903 groupDesc.Buckets = append(groupDesc.Buckets, &bucket)
Esin Karamanccb714b2019-11-29 15:02:06 +00003904 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003905 return &groupEntry
3906}