blob: f2fec2354cd168960abebc74faf78e38834dfa81 [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
Esin Karamand519bbf2020-07-01 11:16:03 +00002675// DeleteGroup deletes a group from the device
2676func (f *OpenOltFlowMgr) DeleteGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
2677 logger.Debugw(ctx, "delete-group", log.Fields{"group": group})
2678 if group == nil {
2679 logger.Error(ctx, "unable-to-delete-group--invalid-argument--group-is-nil")
2680 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
2681 }
2682
2683 groupToOlt := openoltpb2.Group{
2684 GroupId: group.Desc.GroupId,
2685 }
2686
2687 logger.Debugw(ctx, "deleting-group-from-device", log.Fields{"groupToOlt": groupToOlt})
2688 _, err := f.deviceHandler.Client.DeleteGroup(ctx, &groupToOlt)
2689 if err != nil {
2690 logger.Errorw(ctx, "delete-group-failed-on-dev", log.Fields{"groupToOlt": groupToOlt, "err": err})
2691 return olterrors.NewErrAdapter("delete-group-operation-failed", log.Fields{"groupToOlt": groupToOlt}, err)
2692 }
2693 //remove group from the store
2694 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, group.Desc.GroupId, false); err != nil {
2695 return olterrors.NewErrPersistence("delete", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
2696 }
2697 logger.Debugw(ctx, "delete-group-operation-performed-on-the-device-successfully ", log.Fields{"groupToOlt": groupToOlt})
2698 return nil
2699}
2700
Esin Karamanccb714b2019-11-29 15:02:06 +00002701//buildGroupAction creates and returns a group action
2702func (f *OpenOltFlowMgr) buildGroupAction() *openoltpb2.Action {
2703 var actionCmd openoltpb2.ActionCmd
2704 var action openoltpb2.Action
2705 action.Cmd = &actionCmd
2706 //pop outer vlan
2707 action.Cmd.RemoveOuterTag = true
2708 return &action
2709}
2710
2711// ModifyGroup updates the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002712func (f *OpenOltFlowMgr) ModifyGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002713 logger.Infow(ctx, "modify-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002714 if group == nil || group.Desc == nil {
Jonathan Hartc4b19112020-04-02 11:21:45 -07002715 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002716 }
2717
Neha Sharma96b7bf22020-06-15 10:37:32 +00002718 newGroup := f.buildGroup(ctx, group.Desc.GroupId, group.Desc.Buckets)
Esin Karamanccb714b2019-11-29 15:02:06 +00002719 //get existing members of the group
npujarec5762e2020-01-01 14:08:48 +05302720 val, groupExists, err := f.GetFlowGroupFromKVStore(ctx, group.Desc.GroupId, false)
Esin Karamanccb714b2019-11-29 15:02:06 +00002721
2722 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002723 return olterrors.NewErrNotFound("flow-group-in-kv-store", log.Fields{"groupId": group.Desc.GroupId}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002724 }
2725
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002726 var current *openoltpb2.Group // represents the group on the device
Esin Karamanccb714b2019-11-29 15:02:06 +00002727 if groupExists {
2728 // group already exists
Neha Sharma96b7bf22020-06-15 10:37:32 +00002729 current = f.buildGroup(ctx, group.Desc.GroupId, val.Desc.GetBuckets())
2730 logger.Debugw(ctx, "modify-group--group exists",
Shrey Baid26912972020-04-16 21:02:31 +05302731 log.Fields{
2732 "group on the device": val,
2733 "new": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002734 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002735 current = f.buildGroup(ctx, group.Desc.GroupId, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002736 }
2737
Neha Sharma96b7bf22020-06-15 10:37:32 +00002738 logger.Debugw(ctx, "modify-group--comparing-current-and-new",
Shrey Baid26912972020-04-16 21:02:31 +05302739 log.Fields{
2740 "group on the device": current,
2741 "new": newGroup})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002742 // get members to be added
Andrea Campanellac63bba92020-03-10 17:01:04 +01002743 membersToBeAdded := f.findDiff(current, newGroup)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002744 // get members to be removed
Andrea Campanellac63bba92020-03-10 17:01:04 +01002745 membersToBeRemoved := f.findDiff(newGroup, current)
Esin Karamanccb714b2019-11-29 15:02:06 +00002746
Neha Sharma96b7bf22020-06-15 10:37:32 +00002747 logger.Infow(ctx, "modify-group--differences found", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302748 "membersToBeAdded": membersToBeAdded,
2749 "membersToBeRemoved": membersToBeRemoved,
2750 "groupId": group.Desc.GroupId})
Esin Karamanccb714b2019-11-29 15:02:06 +00002751
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002752 groupToOlt := openoltpb2.Group{
2753 GroupId: group.Desc.GroupId,
2754 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002755 var errAdd, errRemoved error
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002756 if membersToBeAdded != nil && len(membersToBeAdded) > 0 {
2757 groupToOlt.Command = openoltpb2.Group_ADD_MEMBERS
2758 groupToOlt.Members = membersToBeAdded
2759 //execute addMembers
Neha Sharma96b7bf22020-06-15 10:37:32 +00002760 errAdd = f.callGroupAddRemove(ctx, &groupToOlt)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002761 }
2762 if membersToBeRemoved != nil && len(membersToBeRemoved) > 0 {
2763 groupToOlt.Command = openoltpb2.Group_REMOVE_MEMBERS
2764 groupToOlt.Members = membersToBeRemoved
2765 //execute removeMembers
Neha Sharma96b7bf22020-06-15 10:37:32 +00002766 errRemoved = f.callGroupAddRemove(ctx, &groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002767 }
2768
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002769 //save the modified group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002770 if errAdd == nil && errRemoved == nil {
npujarec5762e2020-01-01 14:08:48 +05302771 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, false); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002772 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002773 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002774 logger.Infow(ctx, "modify-group-was-success--storing-group",
Shrey Baid26912972020-04-16 21:02:31 +05302775 log.Fields{
2776 "group": group,
2777 "existingGroup": current})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002778 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002779 logger.Warnw(ctx, "one-of-the-group-add/remove-operations-failed--cannot-save-group-modifications",
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002780 log.Fields{"group": group})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002781 if errAdd != nil {
2782 return errAdd
2783 }
2784 return errRemoved
Esin Karamanccb714b2019-11-29 15:02:06 +00002785 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002786 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002787}
2788
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002789//callGroupAddRemove performs add/remove buckets operation for the indicated group
Neha Sharma96b7bf22020-06-15 10:37:32 +00002790func (f *OpenOltFlowMgr) callGroupAddRemove(ctx context.Context, group *openoltpb2.Group) error {
2791 if err := f.performGroupOperation(ctx, group); err != nil {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002792 st, _ := status.FromError(err)
2793 //ignore already exists error code
2794 if st.Code() != codes.AlreadyExists {
Andrea Campanellac63bba92020-03-10 17:01:04 +01002795 return olterrors.NewErrGroupOp("groupAddRemove", group.GroupId, log.Fields{"status": st}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002796 }
2797 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002798 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002799}
2800
2801//findDiff compares group members and finds members which only exists in groups2
2802func (f *OpenOltFlowMgr) findDiff(group1 *openoltpb2.Group, group2 *openoltpb2.Group) []*openoltpb2.GroupMember {
2803 var members []*openoltpb2.GroupMember
2804 for _, bucket := range group2.Members {
2805 if !f.contains(group1.Members, bucket) {
2806 // bucket does not exist and must be added
2807 members = append(members, bucket)
2808 }
2809 }
2810 return members
2811}
2812
2813//contains returns true if the members list contains the given member; false otherwise
2814func (f *OpenOltFlowMgr) contains(members []*openoltpb2.GroupMember, member *openoltpb2.GroupMember) bool {
2815 for _, groupMember := range members {
2816 if groupMember.InterfaceId == member.InterfaceId {
2817 return true
2818 }
2819 }
2820 return false
2821}
2822
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002823//performGroupOperation call performGroupOperation operation of openolt proto
Neha Sharma96b7bf22020-06-15 10:37:32 +00002824func (f *OpenOltFlowMgr) performGroupOperation(ctx context.Context, group *openoltpb2.Group) error {
2825 logger.Debugw(ctx, "sending-group-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05302826 log.Fields{
2827 "groupToOlt": group,
2828 "command": group.Command})
Esin Karamanccb714b2019-11-29 15:02:06 +00002829 _, err := f.deviceHandler.Client.PerformGroupOperation(context.Background(), group)
2830 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002831 return olterrors.NewErrAdapter("group-operation-failed", log.Fields{"groupToOlt": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002832 }
Girish Kumarf26e4882020-03-05 06:49:10 +00002833 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002834}
2835
2836//buildGroup build openoltpb2.Group from given group id and bucket list
Neha Sharma96b7bf22020-06-15 10:37:32 +00002837func (f *OpenOltFlowMgr) buildGroup(ctx context.Context, groupID uint32, buckets []*ofp.OfpBucket) *openoltpb2.Group {
Esin Karamanccb714b2019-11-29 15:02:06 +00002838 group := openoltpb2.Group{
2839 GroupId: groupID}
2840 // create members of the group
2841 if buckets != nil {
2842 for _, ofBucket := range buckets {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002843 member := f.buildMember(ctx, ofBucket)
Esin Karamanccb714b2019-11-29 15:02:06 +00002844 if member != nil && !f.contains(group.Members, member) {
2845 group.Members = append(group.Members, member)
2846 }
2847 }
2848 }
2849 return &group
2850}
2851
2852//buildMember builds openoltpb2.GroupMember from an OpenFlow bucket
Neha Sharma96b7bf22020-06-15 10:37:32 +00002853func (f *OpenOltFlowMgr) buildMember(ctx context.Context, ofBucket *ofp.OfpBucket) *openoltpb2.GroupMember {
Esin Karamanccb714b2019-11-29 15:02:06 +00002854 var outPort uint32
2855 outPortFound := false
2856 for _, ofAction := range ofBucket.Actions {
2857 if ofAction.Type == ofp.OfpActionType_OFPAT_OUTPUT {
2858 outPort = ofAction.GetOutput().Port
2859 outPortFound = true
2860 }
2861 }
2862
2863 if !outPortFound {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002864 logger.Debugw(ctx, "bucket-skipped-since-no-out-port-found-in-it", log.Fields{"ofBucket": ofBucket})
Esin Karamanccb714b2019-11-29 15:02:06 +00002865 return nil
2866 }
2867 interfaceID := IntfIDFromUniPortNum(outPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002868 logger.Debugw(ctx, "got-associated-interface-id-of-the-port",
Shrey Baid26912972020-04-16 21:02:31 +05302869 log.Fields{
2870 "portNumber:": outPort,
2871 "interfaceId:": interfaceID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002872 if groupInfo, ok := f.interfaceToMcastQueueMap[interfaceID]; ok {
2873 member := openoltpb2.GroupMember{
2874 InterfaceId: interfaceID,
2875 InterfaceType: openoltpb2.GroupMember_PON,
2876 GemPortId: groupInfo.gemPortID,
2877 Priority: groupInfo.servicePriority,
2878 }
2879 //add member to the group
2880 return &member
2881 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002882 logger.Warnf(ctx, "bucket-skipped-since-interface-2-gem-mapping-cannot-be-found", log.Fields{"ofBucket": ofBucket})
Esin Karamanccb714b2019-11-29 15:02:06 +00002883 return nil
2884}
2885
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002886//sendTPDownloadMsgToChild send payload
Neha Sharma96b7bf22020-06-15 10:37:32 +00002887func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002888
Neha Sharma96b7bf22020-06-15 10:37:32 +00002889 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302890 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002891 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302892 log.Fields{
2893 "intf-id": intfID,
2894 "onu-id": onuID,
2895 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002896 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302897 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002898 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002899
Neha Sharma96b7bf22020-06-15 10:37:32 +00002900 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002901 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002902 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
manikkaraj k17652a72019-05-06 09:06:36 -04002903 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
2904 tpDownloadMsg,
2905 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05302906 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002907 onuDev.deviceType,
2908 onuDev.deviceID,
2909 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002910 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302911 return olterrors.NewErrCommunication("send-techprofile-download-request",
2912 log.Fields{
2913 "from-adapter": f.deviceHandler.device.Type,
2914 "to-adapter": onuDev.deviceType,
2915 "onu-id": onuDev.deviceID,
2916 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002917 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002918 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302919 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302920}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002921
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302922//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002923func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302924
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002925 f.onuGemInfoLock.Lock()
2926 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002927
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302928 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2929 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002930 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002931 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302932 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002933 logger.Infow(ctx, "updated-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302934 log.Fields{
2935 "intf-id": intfID,
2936 "onu-id": onuID,
2937 "serial-num": serialNum,
2938 "onu": onu,
2939 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002940 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002941}
2942
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302943//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302944func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002945
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002946 f.onuGemInfoLock.Lock()
2947 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002948
Neha Sharma96b7bf22020-06-15 10:37:32 +00002949 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302950 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002951 "gem-port-id": gemPort,
2952 "intf-id": intfID,
2953 "onu-id": onuID,
2954 "device-id": f.deviceHandler.device.Id,
2955 "onu-gem": f.onuGemInfo[intfID]})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302956 onugem := f.onuGemInfo[intfID]
2957 // update the gem to the local cache as well as to kv strore
2958 for idx, onu := range onugem {
2959 if onu.OnuID == onuID {
2960 // check if gem already exists , else update the cache and kvstore
2961 for _, gem := range onu.GemPorts {
2962 if gem == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002963 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302964 log.Fields{
2965 "gem": gemPort,
2966 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302967 return
2968 }
2969 }
2970 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
2971 f.onuGemInfo[intfID] = onugem
2972 }
2973 }
npujarec5762e2020-01-01 14:08:48 +05302974 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302975 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002976 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302977 log.Fields{
2978 "intf-id": intfID,
2979 "onu-id": onuID,
2980 "gemPort": gemPort,
2981 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002982 return
2983 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002984 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302985 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002986 "gem-port-id": gemPort,
2987 "intf-id": intfID,
2988 "onu-id": onuID,
2989 "device-id": f.deviceHandler.device.Id,
2990 "onu-gem": f.onuGemInfo[intfID]})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002991}
2992
2993// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002994
2995//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 +00002996func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(ctx context.Context, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302997
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002998 f.onuGemInfoLock.RLock()
2999 defer f.onuGemInfoLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303000
Neha Sharma96b7bf22020-06-15 10:37:32 +00003001 logger.Infow(ctx, "getting-onu-id-from-gem-port-and-pon-port",
Shrey Baid26912972020-04-16 21:02:31 +05303002 log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003003 "device-id": f.deviceHandler.device.Id,
3004 "onu-geminfo": f.onuGemInfo[intfID],
3005 "intf-id": intfID,
3006 "gemport-id": gemPortID})
Matteo Scandolod625b4c2020-04-02 16:16:01 -07003007
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303008 // get onuid from the onugem info cache
3009 onugem := f.onuGemInfo[intfID]
Matteo Scandolod625b4c2020-04-02 16:16:01 -07003010
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303011 for _, onu := range onugem {
3012 for _, gem := range onu.GemPorts {
3013 if gem == gemPortID {
3014 return onu.OnuID, nil
3015 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003016 }
3017 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003018 logger.Errorw(ctx, "onu-id-from-gem-port-not-found", log.Fields{
3019 "gem-port-id": gemPortID,
3020 "interface-id": intfID,
3021 "all-gems-on-port": onu,
3022 })
Thomas Lee S94109f12020-03-03 16:39:29 +05303023 return uint32(0), olterrors.NewErrNotFound("onu-id", log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003024 "interface-id": intfID,
3025 "gem-port-id": gemPortID},
Girish Kumarf26e4882020-03-05 06:49:10 +00003026 nil)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003027}
3028
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003029//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05303030func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003031 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003032 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003033 var err error
3034
3035 if packetIn.IntfType == "pon" {
3036 // packet indication does not have serial number , so sending as nil
Neha Sharma96b7bf22020-06-15 10:37:32 +00003037 if onuID, err = f.getOnuIDfromGemPortMap(ctx, packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003038 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003039 return logicalPortNum, err
3040 }
3041 if packetIn.PortNo != 0 {
3042 logicalPortNum = packetIn.PortNo
3043 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003044 uniID := uint32(0) // FIXME - multi-uni support
Neha Sharma96b7bf22020-06-15 10:37:32 +00003045 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003046 }
3047 // Store the gem port through which the packet_in came. Use the same gem port for packet_out
Esin Karaman7fb80c22020-07-16 14:23:33 +00003048 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003049 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003050 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003051 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003052 logger.Infow(ctx, "retrieved-logicalport-from-packet-in",
Shrey Baid26912972020-04-16 21:02:31 +05303053 log.Fields{
3054 "logical-port-num": logicalPortNum,
3055 "intf-type": packetIn.IntfType,
3056 "packet": hex.EncodeToString(packetIn.Pkt),
3057 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003058 return logicalPortNum, nil
3059}
3060
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003061//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00003062func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003063 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00003064
3065 ctag, priority, err := getCTagFromPacket(ctx, packet)
3066 if err != nil {
3067 return 0, err
3068 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303069
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003070 f.onuGemInfoLock.RLock()
3071 defer f.onuGemInfoLock.RUnlock()
Esin Karaman7fb80c22020-07-16 14:23:33 +00003072 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003073 var ok bool
3074 gemPortID, ok = f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303075 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003076 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05303077 log.Fields{
3078 "pktinkey": pktInkey,
3079 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003080
3081 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003082 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303083 //If gem is not found in cache try to get it from kv store, if found in kv store, update the cache and return.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003084 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303085 if err == nil {
3086 if gemPortID != 0 {
3087 f.packetInGemPort[pktInkey] = gemPortID
Neha Sharma96b7bf22020-06-15 10:37:32 +00003088 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05303089 log.Fields{
3090 "pktinkey": pktInkey,
3091 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303092 return gemPortID, nil
3093 }
3094 }
Shrey Baid26912972020-04-16 21:02:31 +05303095 return uint32(0), olterrors.NewErrNotFound("gem-port",
3096 log.Fields{
3097 "pktinkey": pktInkey,
3098 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003099
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003100}
3101
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003102// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05303103func installFlowOnAllGemports(ctx context.Context,
3104 f1 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003105 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003106 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, tpID uint32) error,
npujarec5762e2020-01-01 14:08:48 +05303107 f2 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05303108 classifier map[string]interface{}, action map[string]interface{},
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303109 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003110 tpID uint32) error,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003111 args map[string]uint32,
3112 classifier map[string]interface{}, action map[string]interface{},
3113 logicalFlow *ofp.OfpFlowStats,
3114 gemPorts []uint32,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003115 TpInst interface{},
Manikkaraj kb1d51442019-07-23 10:41:02 -04003116 FlowType string,
Gamze Abaka724d0852020-03-18 12:10:24 +00003117 direction string,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003118 tpID uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003119 vlanID ...uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003120 logger.Debugw(ctx, "installing-flow-on-all-gem-ports",
Shrey Baid26912972020-04-16 21:02:31 +05303121 log.Fields{
3122 "FlowType": FlowType,
3123 "gemPorts": gemPorts,
3124 "vlan": vlanID})
Girish Gowdrafae935c2020-02-17 19:21:44 +05303125
Gamze Abaka724d0852020-03-18 12:10:24 +00003126 // The bit mapping for a gemport is expressed in tech-profile as a binary string. For example, 0b00000001
3127 // We need to trim prefix "0b", before further processing
3128 // Once the "0b" prefix is trimmed, we iterate each character in the string to identify which index
3129 // in the string is set to binary bit 1 (expressed as char '1' in the binary string).
3130
3131 // If a particular character in the string is set to '1', identify the index of this character from
3132 // the LSB position which marks the PCP bit consumed by the given gem port.
3133 // This PCP bit now becomes a classifier in the flow.
3134
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003135 switch TpInst := TpInst.(type) {
3136 case *tp.TechProfile:
3137 attributes := TpInst.DownstreamGemPortAttributeList
3138 if direction == Upstream {
3139 attributes = TpInst.UpstreamGemPortAttributeList
Gamze Abaka724d0852020-03-18 12:10:24 +00003140 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003141
3142 for _, gemPortAttribute := range attributes {
3143 if direction == Downstream && strings.ToUpper(gemPortAttribute.IsMulticast) == "TRUE" {
3144 continue
Gamze Abaka724d0852020-03-18 12:10:24 +00003145 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003146 gemPortID := gemPortAttribute.GemportID
3147 if allPbitsMarked(gemPortAttribute.PbitMap) {
3148 classifier[VlanPcp] = uint32(VlanPCPMask)
3149 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3150 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3151 } else if FlowType == EapolFlow {
3152 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3153 }
3154 } else {
3155 for pos, pbitSet := range strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix) {
3156 if pbitSet == BinaryBit1 {
3157 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3158 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3159 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3160 } else if FlowType == EapolFlow {
3161 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3162 }
3163 }
3164 }
3165 }
3166 }
3167 case *tp.EponProfile:
3168 if direction == Upstream {
3169 attributes := TpInst.UpstreamQueueAttributeList
3170 for _, queueAttribute := range attributes {
3171 gemPortID := queueAttribute.GemportID
3172 if allPbitsMarked(queueAttribute.PbitMap) {
3173 classifier[VlanPcp] = uint32(VlanPCPMask)
Gamze Abaka724d0852020-03-18 12:10:24 +00003174 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003175 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
Gamze Abaka724d0852020-03-18 12:10:24 +00003176 } else if FlowType == EapolFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003177 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 +00003178 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003179 } else {
3180 for pos, pbitSet := range strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix) {
3181 if pbitSet == BinaryBit1 {
3182 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3183 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3184 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3185 } else if FlowType == EapolFlow {
3186 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3187 }
3188 }
3189 }
3190 }
3191 }
3192 } else {
3193 attributes := TpInst.DownstreamQueueAttributeList
3194 for _, queueAttribute := range attributes {
3195 gemPortID := queueAttribute.GemportID
3196 if allPbitsMarked(queueAttribute.PbitMap) {
3197 classifier[VlanPcp] = uint32(VlanPCPMask)
3198 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3199 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3200 } else if FlowType == EapolFlow {
3201 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3202 }
3203 } else {
3204 for pos, pbitSet := range strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix) {
3205 if pbitSet == BinaryBit1 {
3206 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3207 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3208 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3209 } else if FlowType == EapolFlow {
3210 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3211 }
3212 }
3213 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05303214 }
3215 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04003216 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003217 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00003218 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpInst": TpInst})
Manikkaraj kb1d51442019-07-23 10:41:02 -04003219 }
3220}
3221
Gamze Abaka724d0852020-03-18 12:10:24 +00003222func allPbitsMarked(pbitMap string) bool {
3223 for pos, pBit := range pbitMap {
3224 if pos >= 2 && pBit != BinaryBit1 {
3225 return false
3226 }
3227 }
3228 return true
3229}
3230
David K. Bainbridge794735f2020-02-11 21:01:37 -08003231func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003232 logger.Debug(ctx, "adding-trap-dhcp-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003233 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003234 classifier[PacketTagType] = DoubleTag
3235 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003236 /* We manage flowId resource pool on per PON port basis.
3237 Since this situation is tricky, as a hack, we pass the NNI port
3238 index (network_intf_id) as PON port Index for the flowId resource
3239 pool. Also, there is no ONU Id available for trapping DHCP packets
3240 on NNI port, use onu_id as -1 (invalid)
3241 ****************** CAVEAT *******************
3242 This logic works if the NNI Port Id falls within the same valid
3243 range of PON Port Ids. If this doesn't work for some OLT Vendor
3244 we need to have a re-look at this.
3245 *********************************************
3246 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003247 onuID := -1
3248 uniID := -1
3249 gemPortID := -1
3250 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00003251 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303252 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303253 return olterrors.NewErrNotFound("nni-intreface-id",
3254 log.Fields{
3255 "classifier": classifier,
3256 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003257 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303258 }
3259
Neha Sharma96b7bf22020-06-15 10:37:32 +00003260 flowStoreCookie := getFlowStoreCookie(ctx, classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303261 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003262 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003263 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003264 }
Gamze Abaka724d0852020-03-18 12:10:24 +00003265 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003266 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303267 return olterrors.NewErrNotFound("dhcp-trap-nni-flow-id",
3268 log.Fields{
3269 "interface-id": networkInterfaceID,
3270 "onu-id": onuID,
3271 "uni-id": uniID,
3272 "gem-port-id": gemPortID,
3273 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003274 err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003275 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003276 classifierProto, err := makeOpenOltClassifierField(classifier)
3277 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003278 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003279 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003280 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003281 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003282 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003283 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003284 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003285 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003286 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3287 OnuId: int32(onuID), // OnuId not required
3288 UniId: int32(uniID), // UniId not used
3289 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07003290 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003291 AllocId: int32(allocID), // AllocId not used
3292 NetworkIntfId: int32(networkInterfaceID),
3293 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003294 Classifier: classifierProto,
3295 Action: actionProto,
3296 Priority: int32(logicalFlow.Priority),
3297 Cookie: logicalFlow.Cookie,
3298 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003299 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003300 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003301 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003302 logger.Info(ctx, "dhcp-trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003303 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3304 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3305 int32(onuID),
3306 int32(uniID),
3307 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003308 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003309 }
3310 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003311}
salmansiddiqui7ac62132019-08-22 03:58:50 +00003312
Esin Karamanae41e2b2019-12-17 18:13:13 +00003313//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
3314func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
3315 var packetType string
3316 ovid, ivid := false, false
3317 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
3318 vid := vlanID & VlanvIDMask
3319 if vid != ReservedVlan {
3320 ovid = true
3321 }
3322 }
3323 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
3324 vid := uint32(metadata)
3325 if vid != ReservedVlan {
3326 ivid = true
3327 }
3328 }
3329 if ovid && ivid {
3330 packetType = DoubleTag
3331 } else if !ovid && !ivid {
3332 packetType = Untagged
3333 } else {
3334 packetType = SingleTag
3335 }
3336 return packetType
3337}
3338
3339//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08003340func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003341 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003342 action := make(map[string]interface{})
3343 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
3344 action[TrapToHost] = true
3345 /* We manage flowId resource pool on per PON port basis.
3346 Since this situation is tricky, as a hack, we pass the NNI port
3347 index (network_intf_id) as PON port Index for the flowId resource
3348 pool. Also, there is no ONU Id available for trapping packets
3349 on NNI port, use onu_id as -1 (invalid)
3350 ****************** CAVEAT *******************
3351 This logic works if the NNI Port Id falls within the same valid
3352 range of PON Port Ids. If this doesn't work for some OLT Vendor
3353 we need to have a re-look at this.
3354 *********************************************
3355 */
3356 onuID := -1
3357 uniID := -1
3358 gemPortID := -1
3359 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00003360 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003361 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303362 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003363 "classifier": classifier,
3364 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003365 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003366 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003367 flowStoreCookie := getFlowStoreCookie(ctx, classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303368 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003369 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003370 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003371 }
npujarec5762e2020-01-01 14:08:48 +05303372 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003373 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303374 return olterrors.NewErrNotFound("igmp-flow-id",
3375 log.Fields{
3376 "interface-id": networkInterfaceID,
3377 "onu-id": onuID,
3378 "uni-id": uniID,
3379 "gem-port-id": gemPortID,
3380 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003381 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003382 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003383 classifierProto, err := makeOpenOltClassifierField(classifier)
3384 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003385 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003386 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003387 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003388 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003389 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003390 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003391 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003392 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003393 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3394 OnuId: int32(onuID), // OnuId not required
3395 UniId: int32(uniID), // UniId not used
3396 FlowId: flowID,
3397 FlowType: Downstream,
3398 AllocId: int32(allocID), // AllocId not used
3399 NetworkIntfId: int32(networkInterfaceID),
3400 GemportId: int32(gemPortID), // GemportId not used
3401 Classifier: classifierProto,
3402 Action: actionProto,
3403 Priority: int32(logicalFlow.Priority),
3404 Cookie: logicalFlow.Cookie,
3405 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003406 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003407 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003408 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003409 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003410 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3411 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3412 int32(onuID),
3413 int32(uniID),
3414 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003415 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003416 }
3417 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003418}
3419
salmansiddiqui7ac62132019-08-22 03:58:50 +00003420func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
3421 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05303422 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003423 }
3424 if Dir == tp_pb.Direction_UPSTREAM {
3425 return "upstream", nil
3426 } else if Dir == tp_pb.Direction_DOWNSTREAM {
3427 return "downstream", nil
3428 }
3429 return "", nil
3430}
3431
npujarec5762e2020-01-01 14:08:48 +05303432func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003433 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003434 tpID uint32, uni string) {
Gamze Abakafee36392019-10-03 11:17:24 +00003435 var gemPort uint32
3436 intfID := args[IntfID]
3437 onuID := args[OnuID]
3438 uniID := args[UniID]
3439 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003440 allocID := args[AllocID]
salmansiddiqui7ac62132019-08-22 03:58:50 +00003441 if ipProto, ok := classifierInfo[IPProto]; ok {
3442 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003443 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003444 "tp-id": tpID,
3445 "alloc-id": allocID,
3446 "intf-id": intfID,
3447 "onu-id": onuID,
3448 "uni-id": uniID,
3449 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003450 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003451 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003452 tp_pb.Direction_UPSTREAM,
3453 pcp.(uint32))
3454 //Adding DHCP upstream flow
Gamze Abaka724d0852020-03-18 12:10:24 +00003455
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003456 f.addDHCPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003457 } else {
3458 //Adding DHCP upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003459 installFlowOnAllGemports(ctx, f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, DhcpFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003460 }
3461
Girish Gowdra32625212020-04-29 11:26:35 -07003462 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003463 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05303464 log.Fields{
3465 "intf-id": intfID,
3466 "onu-id": onuID,
3467 "uni-id": uniID,
3468 "classifier-info:": classifierInfo})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003469 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003470 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
Esin Karamanae41e2b2019-12-17 18:13:13 +00003471 tp_pb.Direction_UPSTREAM,
3472 pcp.(uint32))
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003473 f.addIGMPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003474 } else {
3475 //Adding IGMP upstream flow to all gem ports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003476 installFlowOnAllGemports(ctx, f.addIGMPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, IgmpFlow, Upstream, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003477 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003478 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003479 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003480 return
3481 }
3482 } else if ethType, ok := classifierInfo[EthType]; ok {
3483 if ethType.(uint32) == EapEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003484 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003485 "intf-id": intfID,
3486 "onu-id": onuID,
3487 "uni-id": uniID,
3488 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003489 var vlanID uint32
3490 if val, ok := classifierInfo[VlanVid]; ok {
3491 vlanID = (val.(uint32)) & VlanvIDMask
3492 } else {
3493 vlanID = DefaultMgmtVlan
3494 }
3495 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003496 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003497 tp_pb.Direction_UPSTREAM,
3498 pcp.(uint32))
3499
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003500 f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003501 } else {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003502 installFlowOnAllGemports(ctx, nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, EapolFlow, Upstream, tpID, vlanID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003503 }
3504 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003505 } else if _, ok := actionInfo[PushVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003506 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003507 "intf-id": intfID,
3508 "onu-id": onuID,
3509 "uni-id": uniID,
3510 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003511 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003512 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003513 tp_pb.Direction_UPSTREAM,
3514 pcp.(uint32))
3515 //Adding HSIA upstream flow
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003516 f.addUpstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003517 } else {
3518 //Adding HSIA upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003519 installFlowOnAllGemports(ctx, f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003520 }
3521 } else if _, ok := actionInfo[PopVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003522 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003523 "intf-id": intfID,
3524 "onu-id": onuID,
3525 "uni-id": uniID,
3526 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003527 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003528 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05003529 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003530 pcp.(uint32))
3531 //Adding HSIA downstream flow
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003532 f.addDownstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003533 } else {
3534 //Adding HSIA downstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003535 installFlowOnAllGemports(ctx, f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Downstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003536 }
3537 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003538 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05303539 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003540 "intf-id": intfID,
3541 "onu-id": onuID,
3542 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05303543 "classifier": classifierInfo,
3544 "action": actionInfo,
3545 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003546 return
3547 }
3548 // Send Techprofile download event to child device in go routine as it takes time
Neha Sharma96b7bf22020-06-15 10:37:32 +00003549 go f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003550}
3551
Gamze Abakafee36392019-10-03 11:17:24 +00003552func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
3553 flowIDList := f.flowsUsedByGemPort[gemPK]
3554 if len(flowIDList) > 1 {
3555 return true
3556 }
3557 return false
3558}
3559
npujarec5762e2020-01-01 14:08:48 +05303560func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
3561 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00003562 tpGemPorts := tpInst.UpstreamGemPortAttributeList
3563 for _, currentGemPort := range currentGemPorts {
3564 for _, tpGemPort := range tpGemPorts {
3565 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
3566 return true, currentGemPort
3567 }
3568 }
3569 }
Girish Gowdra54934262019-11-13 14:19:55 +05303570 if tpInst.InstanceCtrl.Onu == "single-instance" {
3571 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
npujarec5762e2020-01-01 14:08:48 +05303572 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, uint32(onuID), uint32(uniID), tpID)
3573 f.DeleteTechProfileInstance(ctx, ponIntf, uint32(onuID), uint32(uniID), "", tpID)
Girish Gowdra54934262019-11-13 14:19:55 +05303574
3575 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
3576 // still be used on other uni ports.
3577 // So, we need to check and make sure that no other gem port is referring to the given TP ID
3578 // on any other uni port.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003579 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID).([]tp.TechProfile)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003580 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303581 for i := 0; i < len(tpInstances); i++ {
3582 tpI := tpInstances[i]
3583 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05303584 for _, tpGemPort := range tpGemPorts {
3585 if tpGemPort.GemportID != gemPortID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003586 logger.Debugw(ctx, "single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05303587 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05303588 }
3589 }
3590 }
3591 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003592 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00003593 return false, 0
3594}
3595
Neha Sharma96b7bf22020-06-15 10:37:32 +00003596func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003597 for _, field := range flows.GetOfbFields(flow) {
3598 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003599 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003600 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003601 } else if field.Type == flows.ETH_DST {
3602 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003603 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003604 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003605 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003606 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003607 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003608 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003609 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003610 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05303611 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003612 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003613 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003614 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003615 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003616 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003617 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003618 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003619 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003620 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003621 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003622 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003623 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003624 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003625 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003626 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003627 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003628 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003629 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003630 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003631 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003632 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003633 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003634 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003635 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003636 return
3637 }
3638 }
3639}
3640
Neha Sharma96b7bf22020-06-15 10:37:32 +00003641func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003642 for _, action := range flows.GetActions(flow) {
3643 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003644 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003645 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003646 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003647 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003648 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003649 }
Scott Baker355d1742019-10-24 10:57:52 -07003650 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003651 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003652 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003653 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003654 if out := action.GetPush(); out != nil {
3655 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003656 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003657 } else {
3658 actionInfo[PushVlan] = true
3659 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003660 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303661 log.Fields{
3662 "push-tpid": actionInfo[TPID].(uint32),
3663 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003664 }
3665 }
Scott Baker355d1742019-10-24 10:57:52 -07003666 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003667 if out := action.GetSetField(); out != nil {
3668 if field := out.GetField(); field != nil {
3669 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003670 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003671 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003672 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3673 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003674 }
3675 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003676 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003677 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003678 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003679 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003680 }
3681 }
3682 return nil
3683}
3684
Neha Sharma96b7bf22020-06-15 10:37:32 +00003685func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003686 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003687 fieldtype := ofbField.GetType()
3688 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003689 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3690 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003691 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003692 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003693 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003694 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003695 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3696 pcp := ofbField.GetVlanPcp()
3697 actionInfo[VlanPcp] = pcp
3698 log.Debugw("action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003699 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003700 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003701 }
3702 }
3703}
3704
Neha Sharma96b7bf22020-06-15 10:37:32 +00003705func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003706 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003707 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003708 } else {
3709 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003710 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003711 }
3712}
3713
Neha Sharma96b7bf22020-06-15 10:37:32 +00003714func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003715 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003716 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003717 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3718 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003719 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003720 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003721 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303722 log.Fields{
3723 "newinport": classifierInfo[InPort].(uint32),
3724 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003725 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303726 return olterrors.NewErrNotFound("child-in-port",
3727 log.Fields{
3728 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3729 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003730 }
3731 }
3732 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003733 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003734 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003735 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003736 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003737 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003738 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303739 log.Fields{
3740 "newoutport": actionInfo[Output].(uint32),
3741 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003742 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303743 return olterrors.NewErrNotFound("out-port",
3744 log.Fields{
3745 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3746 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003747 }
3748 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3749 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003750 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003751 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003752 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303753 log.Fields{
3754 "newinport": actionInfo[Output].(uint32),
3755 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003756 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303757 return olterrors.NewErrNotFound("nni-port",
3758 log.Fields{
3759 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3760 "in-port": classifierInfo[InPort].(uint32),
3761 "out-port": actionInfo[Output].(uint32),
3762 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003763 }
3764 }
3765 }
3766 return nil
3767}
Gamze Abakafee36392019-10-03 11:17:24 +00003768
Neha Sharma96b7bf22020-06-15 10:37:32 +00003769func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003770 /* Metadata 8 bytes:
3771 Most Significant 2 Bytes = Inner VLAN
3772 Next 2 Bytes = Tech Profile ID(TPID)
3773 Least Significant 4 Bytes = Port ID
3774 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3775 subscriber related flows.
3776 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003777 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003778 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003779 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003780 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003781 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003782 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003783}
3784
3785func appendUnique(slice []uint32, item uint32) []uint32 {
3786 for _, sliceElement := range slice {
3787 if sliceElement == item {
3788 return slice
3789 }
3790 }
3791 return append(slice, item)
3792}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303793
3794// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003795func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303796
3797 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3798 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003799 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003800 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003801 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003802 log.Fields{
3803 "port-number": action[Output].(uint32),
3804 "error": err})
3805 return uint32(0), err
3806 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003807 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303808 return intfID, nil
3809 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003810 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003811 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003812 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003813 log.Fields{
3814 "port-number": action[Output].(uint32),
3815 "error": err})
3816 return uint32(0), err
3817 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003818 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303819 return intfID, nil
3820 }
3821 return uint32(0), nil
3822}
3823
3824// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003825func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3826 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3827 if err != nil {
3828 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3829 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3830 return
3831 }
3832 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003833
3834 f.onuGemInfoLock.Lock()
3835 defer f.onuGemInfoLock.Unlock()
3836
Matt Jeanneret1719a072019-12-20 14:50:14 -05003837 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303838 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003839 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003840 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 +05303841 log.Fields{
3842 "pktinkey": pktInkey,
3843 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003844 return
3845 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303846 }
Matt Jeanneret1719a072019-12-20 14:50:14 -05003847 f.packetInGemPort[pktInkey] = gemPort
3848
npujarec5762e2020-01-01 14:08:48 +05303849 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003850 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 +05303851 log.Fields{
3852 "pktinkey": pktInkey,
3853 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303854 return
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003855
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303856}
3857
Esin Karaman7fb80c22020-07-16 14:23:33 +00003858//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3859func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3860 if packet == nil || len(packet) < 18 {
3861 log.Error("unable-get-c-tag-from-the-packet--invalid-packet-length ")
3862 return 0, 0, errors.New("invalid packet length")
3863 }
3864 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3865 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3866
3867 var index int8
3868 if outerEthType == 0x8100 {
3869 if innerEthType == 0x8100 {
3870 // q-in-q 802.1ad or 802.1q double tagged packet.
3871 // get the inner vlanId
3872 index = 18
3873 } else {
3874 index = 14
3875 }
3876 priority := (packet[index] >> 5) & 0x7
3877 //13 bits composes vlanId value
3878 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3879 return vlan, priority, nil
3880 }
3881 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3882 return 0, 0, nil
3883}
3884
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303885// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303886func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003887
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003888 f.onuGemInfoLock.Lock()
3889 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003890
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303891 onugem := f.onuGemInfo[intfID]
3892 for idx, onu := range onugem {
3893 if onu.OnuID == onuID {
3894 for _, uni := range onu.UniPorts {
3895 if uni == portNum {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003896 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 +05303897 return
3898 }
3899 }
3900 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
3901 f.onuGemInfo[intfID] = onugem
3902 }
3903 }
npujarec5762e2020-01-01 14:08:48 +05303904 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003905
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303906}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303907
npujarec5762e2020-01-01 14:08:48 +05303908func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3909 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303910 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003911 logger.Error(ctx, "failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303912 return
3913 }
3914 for gem, FlowIDs := range flowIDsList {
3915 gemPK := gemPortKey{intf, uint32(gem)}
3916 f.flowsUsedByGemPort[gemPK] = FlowIDs
3917 }
3918 return
3919}
Esin Karamanccb714b2019-11-29 15:02:06 +00003920
3921//loadInterfaceToMulticastQueueMap reads multicast queues per interface from the KV store
3922//and put them into interfaceToMcastQueueMap.
npujarec5762e2020-01-01 14:08:48 +05303923func (f *OpenOltFlowMgr) loadInterfaceToMulticastQueueMap(ctx context.Context) {
3924 storedMulticastQueueMap, err := f.resourceMgr.GetMcastQueuePerInterfaceMap(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00003925 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003926 logger.Error(ctx, "failed-to-get-pon-interface-to-multicast-queue-map")
Esin Karamanccb714b2019-11-29 15:02:06 +00003927 return
3928 }
3929 for intf, queueInfo := range storedMulticastQueueMap {
3930 q := queueInfoBrief{
3931 gemPortID: queueInfo[0],
3932 servicePriority: queueInfo[1],
3933 }
3934 f.interfaceToMcastQueueMap[intf] = &q
3935 }
3936}
3937
3938//GetFlowGroupFromKVStore fetches and returns flow group from the KV store. Returns (nil, false, error) if any problem occurs during
3939//fetching the data. Returns (group, true, nil) if the group is fetched and returned successfully.
3940//Returns (nil, false, nil) if the group does not exists in the KV store.
npujarec5762e2020-01-01 14:08:48 +05303941func (f *OpenOltFlowMgr) GetFlowGroupFromKVStore(ctx context.Context, groupID uint32, cached bool) (*ofp.OfpGroupEntry, bool, error) {
3942 exists, groupInfo, err := f.resourceMgr.GetFlowGroupFromKVStore(ctx, groupID, cached)
Esin Karamanccb714b2019-11-29 15:02:06 +00003943 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003944 return nil, false, olterrors.NewErrNotFound("flow-group", log.Fields{"group-id": groupID}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00003945 }
3946 if exists {
3947 return newGroup(groupInfo.GroupID, groupInfo.OutPorts), exists, nil
3948 }
3949 return nil, exists, nil
3950}
3951
3952func newGroup(groupID uint32, outPorts []uint32) *ofp.OfpGroupEntry {
3953 groupDesc := ofp.OfpGroupDesc{
3954 Type: ofp.OfpGroupType_OFPGT_ALL,
3955 GroupId: groupID,
3956 }
3957 groupEntry := ofp.OfpGroupEntry{
3958 Desc: &groupDesc,
3959 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003960 for i := 0; i < len(outPorts); i++ {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003961 var acts []*ofp.OfpAction
Esin Karamanccb714b2019-11-29 15:02:06 +00003962 acts = append(acts, flows.Output(outPorts[i]))
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003963 bucket := ofp.OfpBucket{
3964 Actions: acts,
3965 }
3966 groupDesc.Buckets = append(groupDesc.Buckets, &bucket)
Esin Karamanccb714b2019-11-29 15:02:06 +00003967 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003968 return &groupEntry
3969}