blob: 61367984f0fd032b7205111f3d5664c98d9aa717 [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"
Matteo Scandolo6056e822019-11-13 14:05:29 -080022 "encoding/hex"
Girish Gowdracefae192020-03-19 18:14:10 -070023 "errors"
manikkaraj kbf256be2019-03-25 00:13:48 +053024 "fmt"
Gamze Abaka7650be62021-02-26 10:50:36 +000025 "strconv"
serkant.uluderya4aff1862020-09-17 23:35:26 +030026 "strings"
27 "sync"
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070028 "time"
serkant.uluderya4aff1862020-09-17 23:35:26 +030029
Mahir Gunyel199570a2021-07-04 15:39:36 -070030 "github.com/opencord/voltha-lib-go/v6/pkg/meters"
31
Girish Gowdra4c3d4602021-07-22 16:33:37 -070032 "github.com/opencord/voltha-lib-go/v6/pkg/flows"
33 "github.com/opencord/voltha-lib-go/v6/pkg/log"
34 tp "github.com/opencord/voltha-lib-go/v6/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080035 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070036 "github.com/opencord/voltha-protos/v4/go/common"
37 ic "github.com/opencord/voltha-protos/v4/go/inter_container"
38 ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
39 openoltpb2 "github.com/opencord/voltha-protos/v4/go/openolt"
40 tp_pb "github.com/opencord/voltha-protos/v4/go/tech_profile"
41 "github.com/opencord/voltha-protos/v4/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040042
Thomas Lee S94109f12020-03-03 16:39:29 +053043 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000044 "google.golang.org/grpc/codes"
45 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053046)
47
48const (
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070049 //IPProtoDhcp flow category
50 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053051
Girish Gowdraa09aeab2020-09-14 16:30:52 -070052 //IgmpProto proto value
53 IgmpProto = 2
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070054
55 //EapEthType eapethtype value
56 EapEthType = 0x888e
57 //LldpEthType lldp ethtype value
58 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000059 //IPv4EthType IPv4 ethernet type value
60 IPv4EthType = 0x800
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -030061 //PPPoEDEthType PPPoE discovery ethernet type value
62 PPPoEDEthType = 0x8863
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070063
Andrea Campanella7acc0b92020-02-14 09:20:49 +010064 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
65 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040066
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070067 //DefaultMgmtVlan default vlan value
68 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053069
manikkaraj kbf256be2019-03-25 00:13:48 +053070 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070071
David K. Bainbridge82efc492019-09-04 09:57:11 -070072 //Upstream constant
73 Upstream = "upstream"
74 //Downstream constant
75 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000076 //Multicast constant
77 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070078 //PacketTagType constant
79 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070080 //Untagged constant
81 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070082 //SingleTag constant
83 SingleTag = "single_tag"
84 //DoubleTag constant
85 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053086
87 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070088
89 //EthType constant
90 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +000091 //EthDst constant
92 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070093 //TPID constant
94 TPID = "tpid"
95 //IPProto constant
96 IPProto = "ip_proto"
97 //InPort constant
98 InPort = "in_port"
99 //VlanVid constant
100 VlanVid = "vlan_vid"
101 //VlanPcp constant
102 VlanPcp = "vlan_pcp"
103
104 //UDPDst constant
105 UDPDst = "udp_dst"
106 //UDPSrc constant
107 UDPSrc = "udp_src"
108 //Ipv4Dst constant
109 Ipv4Dst = "ipv4_dst"
110 //Ipv4Src constant
111 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700112 //Metadata constant
113 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700114 //TunnelID constant
115 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700116 //Output constant
117 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000118 //GroupID constant
119 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700120 // Actions
121
122 //PopVlan constant
123 PopVlan = "pop_vlan"
124 //PushVlan constant
125 PushVlan = "push_vlan"
126 //TrapToHost constant
127 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400128 //MaxMeterBand constant
129 MaxMeterBand = 2
130 //VlanPCPMask contant
131 VlanPCPMask = 0xFF
132 //VlanvIDMask constant
133 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000134 //IntfID constant
135 IntfID = "intfId"
136 //OnuID constant
137 OnuID = "onuId"
138 //UniID constant
139 UniID = "uniId"
140 //PortNo constant
141 PortNo = "portNo"
142 //AllocID constant
143 AllocID = "allocId"
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000144 //GemID constant
145 GemID = "gemId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000146
147 //NoneOnuID constant
148 NoneOnuID = -1
149 //NoneUniID constant
150 NoneUniID = -1
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700151
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700152 // Max number of flows that can be queued per ONU
153 maxConcurrentFlowsPerOnu = 20
manikkaraj kbf256be2019-03-25 00:13:48 +0530154
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700155 bitMapPrefix = "0b"
156 pbit1 = '1'
157)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400158
Gamze Abakafee36392019-10-03 11:17:24 +0000159type schedQueue struct {
160 direction tp_pb.Direction
161 intfID uint32
162 onuID uint32
163 uniID uint32
164 tpID uint32
165 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700166 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000167 meterID uint32
168 flowMetadata *voltha.FlowMetadata
169}
170
Gamze Abaka7650be62021-02-26 10:50:36 +0000171type flowContext struct {
172 intfID uint32
173 onuID uint32
174 uniID uint32
175 portNo uint32
176 classifier map[string]interface{}
177 action map[string]interface{}
178 logicalFlow *ofp.OfpFlowStats
179 allocID uint32
180 gemPortID uint32
181 tpID uint32
182 pbitToGem map[uint32]uint32
183 gemToAes map[uint32]bool
184}
185
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700186// This control block is created per flow add/remove and pushed on the incomingFlows channel slice
187// The flowControlBlock is then picked by the perOnuFlowHandlerRoutine for further processing.
188// There is on perOnuFlowHandlerRoutine routine per ONU that constantly monitors for any incoming
189// flow and processes it serially
190type flowControlBlock struct {
191 ctx context.Context // Flow handler context
192 addFlow bool // if true flow to be added, else removed
193 flow *voltha.OfpFlowStats // Flow message
194 flowMetadata *voltha.FlowMetadata // FlowMetadata that contains flow meter information. This can be nil for Flow remove
195 errChan *chan error // channel to report the Flow handling error
Esin Karamanccb714b2019-11-29 15:02:06 +0000196}
197
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700198//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530199type OpenOltFlowMgr struct {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700200 ponPortIdx uint32 // Pon Port this FlowManager is responsible for
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700201 techprofile tp.TechProfileIf
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700202 deviceHandler *DeviceHandler
203 grpMgr *OpenOltGroupMgr
204 resourceMgr *rsrcMgr.OpenOltResourceMgr
205
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700206 gemToFlowIDs map[uint32][]uint64 // gem port id to flow ids
207 gemToFlowIDsKey sync.RWMutex // lock to be used to access the gemToFlowIDs map
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700208
209 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
210 packetInGemPortLock sync.RWMutex
211
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700212 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700213 onuGemInfoMap map[uint32]*rsrcMgr.OnuGemInfo //onu, gem and uni info local cache -> map of onuID to OnuGemInfo
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700214 // We need to have a global lock on the onuGemInfo map
Girish Gowdra9602eb42020-09-09 15:50:39 -0700215 onuGemInfoLock sync.RWMutex
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700216
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700217 flowIDToGems map[uint64][]uint32
218 flowIDToGemsLock sync.RWMutex
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700219
220 // Slice of channels. Each channel in slice, index by ONU ID, queues flows per ONU.
221 // A go routine per ONU, waits on the unique channel (indexed by ONU ID) for incoming flows (add/remove)
222 incomingFlows []chan flowControlBlock
manikkaraj kbf256be2019-03-25 00:13:48 +0530223}
224
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700225//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700226func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000227 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530228 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530229 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530230
manikkaraj kbf256be2019-03-25 00:13:48 +0530231 flowMgr.deviceHandler = dh
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700232 flowMgr.ponPortIdx = ponPortIdx
Girish Gowdra9602eb42020-09-09 15:50:39 -0700233 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530234 flowMgr.resourceMgr = rMgr
Neha Sharma96b7bf22020-06-15 10:37:32 +0000235 if err = flowMgr.populateTechProfilePerPonPort(ctx); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700236 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"err": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530237 return nil
238 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700239 flowMgr.gemToFlowIDs = make(map[uint32][]uint64)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530240 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700241 flowMgr.flowIDToGems = make(map[uint64][]uint32)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700242
243 // Create a slice of buffered channels for handling concurrent flows per ONU.
244 // The additional entry (+1) is to handle the NNI trap flows on a separate channel from individual ONUs channel
245 flowMgr.incomingFlows = make([]chan flowControlBlock, MaxOnusPerPon+1)
246 for i := range flowMgr.incomingFlows {
247 flowMgr.incomingFlows[i] = make(chan flowControlBlock, maxConcurrentFlowsPerOnu)
248 // Spin up a go routine to handling incoming flows (add/remove).
249 // There will be on go routine per ONU.
250 // This routine will be blocked on the flowMgr.incomingFlows[onu-id] channel for incoming flows.
251 go flowMgr.perOnuFlowHandlerRoutine(flowMgr.incomingFlows[i])
252 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700253 flowMgr.onuGemInfoMap = make(map[uint32]*rsrcMgr.OnuGemInfo)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530254 //Load the onugem info cache from kv store on flowmanager start
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700255 onuIDStart := flowMgr.deviceHandler.deviceInfo.OnuIdStart
256 onuIDEnd := flowMgr.deviceHandler.deviceInfo.OnuIdEnd
257 for onuID := onuIDStart; onuID <= onuIDEnd; onuID++ {
258 // check for a valid serial number in onuGem as GetOnuGemInfo can return nil error in case of nothing found in the path.
259 onugem, err := rMgr.GetOnuGemInfo(ctx, onuID, ponPortIdx)
260 if err == nil && onugem != nil && onugem.SerialNumber != "" {
261 flowMgr.onuGemInfoMap[onuID] = onugem
262 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530263 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700264
265 //Load flowID list per gem map And gemIDs per flow per interface from the kvstore.
266 flowMgr.loadFlowIDsForGemAndGemIDsForFlow(ctx)
267
Esin Karamanccb714b2019-11-29 15:02:06 +0000268 //load interface to multicast queue map from kv store
Girish Gowdra9602eb42020-09-09 15:50:39 -0700269 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000270 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530271 return &flowMgr
272}
273
Kent Hagermane6ff1012020-07-14 15:07:53 -0400274func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700275 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
276 // Flow is not replicated in this case, we need to register the flow for a single gem-port
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700277 return f.registerFlowIDForGemAndGemIDForFlow(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowFromCore)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700278 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
279 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
280 for _, gemPort := range deviceFlow.PbitToGemport {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700281 if err := f.registerFlowIDForGemAndGemIDForFlow(ctx, uint32(deviceFlow.AccessIntfId), gemPort, flowFromCore); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700282 return err
283 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700284 }
Gamze Abakafee36392019-10-03 11:17:24 +0000285 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700286 return nil
287}
288
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700289func (f *OpenOltFlowMgr) registerFlowIDForGemAndGemIDForFlow(ctx context.Context, accessIntfID uint32, gemPortID uint32, flowFromCore *ofp.OfpFlowStats) error {
290 // update gem->flows map
291 f.gemToFlowIDsKey.Lock()
292 flowIDList, ok := f.gemToFlowIDs[gemPortID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700293 if !ok {
294 flowIDList = []uint64{flowFromCore.Id}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700295 } else {
296 flowIDList = appendUnique64bit(flowIDList, flowFromCore.Id)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700297 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700298 f.gemToFlowIDs[gemPortID] = flowIDList
299 f.gemToFlowIDsKey.Unlock()
300
301 // update flow->gems map
302 f.flowIDToGemsLock.Lock()
303 if _, ok := f.flowIDToGems[flowFromCore.Id]; !ok {
304 f.flowIDToGems[flowFromCore.Id] = []uint32{gemPortID}
305 } else {
306 f.flowIDToGems[flowFromCore.Id] = appendUnique32bit(f.flowIDToGems[flowFromCore.Id], gemPortID)
307 }
308 f.flowIDToGemsLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700309
310 // update the flowids for a gem to the KVstore
311 return f.resourceMgr.UpdateFlowIDsForGem(ctx, accessIntfID, gemPortID, flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400312}
313
Girish Gowdra9602eb42020-09-09 15:50:39 -0700314func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000315 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
Andrea Campanellabfe08432020-09-11 17:07:03 +0200316 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000317 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530318 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700319 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530320
Neha Sharma96b7bf22020-06-15 10:37:32 +0000321 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530322 "device-id": f.deviceHandler.device.Id,
323 "intf-id": intfID,
324 "onu-id": onuID,
325 "uni-id": uniID,
326 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700327 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530328 "action": actionInfo,
329 "usmeter-iD": UsMeterID,
330 "dsmeter-iD": DsMeterID,
331 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400332 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
333 // is because the flow is an NNI flow and there would be no onu resources associated with it
334 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400335 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200336 cause := "no-onu-id-for-flow"
337 fields := log.Fields{
338 "onu": onuID,
339 "port-no": portNo,
340 "classifer": classifierInfo,
341 "action": actionInfo,
342 "device-id": f.deviceHandler.device.Id}
343 logger.Errorw(ctx, cause, fields)
344 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530345 }
346
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700347 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000348 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530349 "uni": uni,
350 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530351
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700352 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
353 "device-id": f.deviceHandler.device.Id,
354 "intf-id": intfID,
355 "onu-id": onuID,
356 "uni-id": uniID,
357 "port-no": portNo,
358 "classifier": classifierInfo,
359 "action": actionInfo,
360 "usmeter-id": UsMeterID,
361 "dsmeter-id": DsMeterID,
362 "tp-id": TpID})
363 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
364 if allocID == 0 || gemPorts == nil || TpInst == nil {
365 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
366 return olterrors.NewErrNotFound(
367 "alloc-id-gem-ports-tp-unavailable",
368 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400369 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700370 args := make(map[string]uint32)
371 args[IntfID] = intfID
372 args[OnuID] = onuID
373 args[UniID] = uniID
374 args[PortNo] = portNo
375 args[AllocID] = allocID
376
377 /* Flows can be added specific to gemport if p-bits are received.
378 * If no pbit mentioned then adding flows for all gemports
379 */
380 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
381
Andrea Campanellabfe08432020-09-11 17:07:03 +0200382 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530383}
384
salmansiddiqui7ac62132019-08-22 03:58:50 +0000385// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530386func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400387
Neha Sharma96b7bf22020-06-15 10:37:32 +0000388 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530389 log.Fields{"dir": sq.direction,
390 "intf-id": sq.intfID,
391 "onu-id": sq.onuID,
392 "uni-id": sq.uniID,
393 "tp-id": sq.tpID,
394 "meter-id": sq.meterID,
395 "tp-inst": sq.tpInst,
396 "flowmetadata": sq.flowMetadata,
397 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400398
Gamze Abakafee36392019-10-03 11:17:24 +0000399 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000400 if err != nil {
401 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400402 }
403
404 /* Lets make a simple assumption that if the meter-id is present on the KV store,
405 * then the scheduler and queues configuration is applied on the OLT device
406 * in the given direction.
407 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000408
Manikkaraj kb1d51442019-07-23 10:41:02 -0400409 var SchedCfg *tp_pb.SchedulerConfig
Girish Gowdraa482f272021-03-24 23:04:19 -0700410 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400411 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530412 return olterrors.NewErrNotFound("meter",
413 log.Fields{"intf-id": sq.intfID,
414 "onu-id": sq.onuID,
415 "uni-id": sq.uniID,
416 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400417 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000418
Girish Gowdraa482f272021-03-24 23:04:19 -0700419 if meterInfo != nil {
420 logger.Debugw(ctx, "scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id, "meter-id": sq.meterID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700421 if meterInfo.MeterID == sq.meterID {
Girish Gowdraa482f272021-03-24 23:04:19 -0700422 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, true); err != nil {
423 return err
424 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400425 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400426 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530427 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800428 "unsupported": "meter-id",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700429 "kv-store-meter-id": meterInfo.MeterID,
Shrey Baid26912972020-04-16 21:02:31 +0530430 "meter-id-in-flow": sq.meterID,
431 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400432 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000433
Neha Sharma96b7bf22020-06-15 10:37:32 +0000434 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530435 log.Fields{
436 "meter-id": sq.meterID,
437 "direction": Direction,
438 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000439
Gamze Abakafee36392019-10-03 11:17:24 +0000440 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700441 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Gamze Abakafee36392019-10-03 11:17:24 +0000442 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700443 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Girish Kumar8f73fe02019-12-09 13:19:37 +0000444 }
445
Girish Gowdraa482f272021-03-24 23:04:19 -0700446 found := false
447 meterInfo = &rsrcMgr.MeterInfo{}
Gamze Abakafee36392019-10-03 11:17:24 +0000448 if sq.flowMetadata != nil {
449 for _, meter := range sq.flowMetadata.Meters {
450 if sq.meterID == meter.MeterId {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700451 meterInfo.MeterID = meter.MeterId
Girish Gowdraa482f272021-03-24 23:04:19 -0700452 meterInfo.RefCnt = 1 // initialize it to 1, since this is the first flow that referenced the meter id.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000453 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700454 log.Fields{"meter": meter,
Shrey Baid26912972020-04-16 21:02:31 +0530455 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -0700456 found = true
Manikkaraj kb1d51442019-07-23 10:41:02 -0400457 break
458 }
459 }
460 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000461 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400462 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700463 if !found {
Thomas Lee S94109f12020-03-03 16:39:29 +0530464 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800465 "reason": "Could-not-get-meterbands-from-flowMetadata",
466 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530467 "meter-id": sq.meterID,
468 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400469 }
Gamze Abaka01174422021-03-10 06:55:27 +0000470
471 var TrafficShaping *tp_pb.TrafficShapingInfo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700472 if TrafficShaping, err = meters.GetTrafficShapingInfo(ctx, sq.flowMetadata.Meters[0]); err != nil {
Gamze Abaka01174422021-03-10 06:55:27 +0000473 return olterrors.NewErrInvalidValue(log.Fields{
474 "reason": "invalid-meter-config",
475 "meter-id": sq.meterID,
476 "device-id": f.deviceHandler.device.Id}, nil)
477 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400478
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700479 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000480 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400481
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700482 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530483 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
484 log.Fields{"intf-id": sq.intfID,
485 "direction": sq.direction,
486 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400487 }
488
salmansiddiqui7ac62132019-08-22 03:58:50 +0000489 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400490 * store the meter id on the KV store, for further reference.
491 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700492 if err := f.resourceMgr.StoreMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530493 return olterrors.NewErrAdapter("failed-updating-meter-id",
494 log.Fields{"onu-id": sq.onuID,
495 "meter-id": sq.meterID,
496 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400497 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000498 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530499 log.Fields{"direction": Direction,
Girish Gowdraa482f272021-03-24 23:04:19 -0700500 "meter-info": meterInfo,
501 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400502 return nil
503}
504
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700505func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700506 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000507
508 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530509 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
510 log.Fields{"intf-id": sq.intfID,
511 "direction": sq.direction,
512 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000513 }
514
Gamze Abakacb0e6772021-06-10 08:32:12 +0000515 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
516 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
517 log.Fields{
518 "direction": sq.direction,
519 "TrafficScheds": TrafficSched,
520 "device-id": f.deviceHandler.device.Id,
521 "intfID": sq.intfID,
522 "onuID": sq.onuID,
523 "uniID": sq.uniID})
524 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
525 IntfId: sq.intfID, OnuId: sq.onuID,
526 UniId: sq.uniID, PortNo: sq.uniPort,
527 TrafficScheds: TrafficSched}); err != nil {
528 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
529 }
530 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
531 "direction": sq.direction,
532 "traffic-queues": trafficQueues,
533 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000534 }
535
536 // On receiving the CreateTrafficQueues request, the driver should create corresponding
537 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000538 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530539 log.Fields{"direction": sq.direction,
540 "traffic-queues": trafficQueues,
541 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530542 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000543 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
544 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000545 TrafficQueues: trafficQueues,
546 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530547 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000548 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000549 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530550 "direction": sq.direction,
551 "traffic-queues": trafficQueues,
552 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000553
Esin Karamanccb714b2019-11-29 15:02:06 +0000554 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700555 multicastTrafficQueues := f.techprofile.GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance))
Esin Karamanccb714b2019-11-29 15:02:06 +0000556 if len(multicastTrafficQueues) > 0 {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700557 if _, present := f.grpMgr.GetInterfaceToMcastQueueMap(sq.intfID); !present { //assumed that there is only one queue per PON for the multicast service
Esin Karamanccb714b2019-11-29 15:02:06 +0000558 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
559 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000560 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000561 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700562 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000563 gemPortID: multicastQueuePerPonPort.GemportId,
564 servicePriority: multicastQueuePerPonPort.Priority,
565 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700566 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000567 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400568 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700569 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400570 return err
571 }
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 {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700595 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
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 {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700598 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400599 Direction = "downstream"
600 }
601
Girish Gowdraa482f272021-03-24 23:04:19 -0700602 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
Manikkaraj kb1d51442019-07-23 10:41:02 -0400603
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700604 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000605 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000606
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700607 TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000608 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530609 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
610 log.Fields{
611 "intf-id": sq.intfID,
612 "direction": sq.direction,
613 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000614 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400615
npujarec5762e2020-01-01 14:08:48 +0530616 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000617 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
618 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000619 TrafficQueues: TrafficQueues,
620 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000621 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530622 log.Fields{
623 "intf-id": sq.intfID,
624 "traffic-queues": TrafficQueues,
625 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400626 }
Gamze Abakacb0e6772021-06-10 08:32:12 +0000627 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id, "trafficQueues": TrafficQueues})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400628
Gamze Abakacb0e6772021-06-10 08:32:12 +0000629 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
630 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
631 IntfId: sq.intfID, OnuId: sq.onuID,
632 UniId: sq.uniID, PortNo: sq.uniPort,
633 TrafficScheds: TrafficSched}); err != nil {
634 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
635 log.Fields{
636 "intf-id": sq.intfID,
637 "traffic-schedulers": TrafficSched,
638 "onu-id": sq.onuID,
639 "uni-id": sq.uniID,
640 "uni-port": sq.uniPort}, err)
641 }
642
643 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
644 log.Fields{"device-id": f.deviceHandler.device.Id,
645 "intf-id": sq.intfID,
646 "onu-id": sq.onuID,
647 "uni-id": sq.uniID,
648 "uni-port": sq.uniPort})
649
650 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700651 allocID := sq.tpInst.(*tp_pb.TechProfileInstance).UsScheduler.AllocId
Gamze Abakacb0e6772021-06-10 08:32:12 +0000652 f.resourceMgr.FreeAllocID(ctx, sq.intfID, sq.onuID, sq.uniID, allocID)
653 // Delete the TCONT on the ONU.
654 uni := getUniPortPath(f.deviceHandler.device.Id, sq.intfID, int32(sq.onuID), int32(sq.uniID))
655 tpPath := f.getTPpath(ctx, sq.intfID, uni, sq.tpID)
656 if err := f.sendDeleteTcontToChild(ctx, sq.intfID, sq.onuID, sq.uniID, allocID, tpPath); err != nil {
657 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
658 log.Fields{
659 "intf": sq.intfID,
660 "onu-id": sq.onuID,
661 "uni-id": sq.uniID,
662 "device-id": f.deviceHandler.device.Id,
663 "alloc-id": allocID})
664 }
665 }
666 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000667
668 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400669 * delete the meter id on the KV store.
670 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700671 err = f.resourceMgr.RemoveMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400672 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530673 return olterrors.NewErrAdapter("unable-to-remove-meter",
674 log.Fields{
675 "onu": sq.onuID,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700676 "device-id": f.deviceHandler.device.Id,
677 "intf-id": sq.intfID,
678 "onu-id": sq.onuID,
679 "uni-id": sq.uniID,
680 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400681 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000682 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530683 log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530684 "dir": Direction,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700685 "device-id": f.deviceHandler.device.Id,
686 "intf-id": sq.intfID,
687 "onu-id": sq.onuID,
688 "uni-id": sq.uniID,
689 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400690 return err
691}
692
Girish Gowdra197acc12021-08-16 10:59:45 -0700693// We are trying to force remove the schedulers and queues here if one exists for the given key.
694// We ignore any errors encountered in the process. The errors most likely are encountered when
695// the schedulers and queues are already cleared for the given key.
696func (f *OpenOltFlowMgr) forceRemoveSchedulerQueues(ctx context.Context, sq schedQueue) {
697
698 var schedCfg *tp_pb.SchedulerConfig
699 var err error
700 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
701 log.Fields{
702 "direction": sq.direction,
703 "intf-id": sq.intfID,
704 "onu-id": sq.onuID,
705 "uni-id": sq.uniID,
706 "uni-port": sq.uniPort,
707 "tp-id": sq.tpID,
708 "device-id": f.deviceHandler.device.Id})
709 if sq.direction == tp_pb.Direction_UPSTREAM {
710 schedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
711 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
712 schedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
713 }
714
715 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
716 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), schedCfg, TrafficShaping)}
717 TrafficSched[0].TechProfileId = sq.tpID
718
719 // Remove traffic queues. Ignore any errors, just log them.
720 if TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction); err != nil {
721 logger.Errorw(ctx, "error retrieving traffic queue", log.Fields{
722 "direction": sq.direction,
723 "intf-id": sq.intfID,
724 "onu-id": sq.onuID,
725 "uni-id": sq.uniID,
726 "uni-port": sq.uniPort,
727 "tp-id": sq.tpID,
728 "device-id": f.deviceHandler.device.Id,
729 "err": err})
730 } else {
731 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
732 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
733 UniId: sq.uniID, PortNo: sq.uniPort,
734 TrafficQueues: TrafficQueues,
735 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
736 logger.Warnw(ctx, "error removing traffic queue", log.Fields{
737 "direction": sq.direction,
738 "intf-id": sq.intfID,
739 "onu-id": sq.onuID,
740 "uni-id": sq.uniID,
741 "uni-port": sq.uniPort,
742 "tp-id": sq.tpID,
743 "device-id": f.deviceHandler.device.Id,
744 "err": err})
745
746 } else {
747 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
748 "direction": sq.direction,
749 "intf-id": sq.intfID,
750 "onu-id": sq.onuID,
751 "uni-id": sq.uniID,
752 "uni-port": sq.uniPort,
753 "tp-id": sq.tpID})
754 }
755 }
756
757 // Remove traffic schedulers. Ignore any errors, just log them.
758 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
759 IntfId: sq.intfID, OnuId: sq.onuID,
760 UniId: sq.uniID, PortNo: sq.uniPort,
761 TrafficScheds: TrafficSched}); err != nil {
762 logger.Warnw(ctx, "error removing traffic scheduler", log.Fields{
763 "direction": sq.direction,
764 "intf-id": sq.intfID,
765 "onu-id": sq.onuID,
766 "uni-id": sq.uniID,
767 "uni-port": sq.uniPort,
768 "tp-id": sq.tpID,
769 "device-id": f.deviceHandler.device.Id,
770 "err": err})
771 } else {
772 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
773 "direction": sq.direction,
774 "intf-id": sq.intfID,
775 "onu-id": sq.onuID,
776 "uni-id": sq.uniID,
777 "uni-port": sq.uniPort,
778 "tp-id": sq.tpID})
779 }
780}
781
Gamze Abakafee36392019-10-03 11:17:24 +0000782// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700783func (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 +0000784 var allocIDs []uint32
785 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530786 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530787 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000788 var err error
npujarec5762e2020-01-01 14:08:48 +0530789 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
790 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000791 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530792
Neha Sharma96b7bf22020-06-15 10:37:32 +0000793 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530794 "intf-id": intfID,
795 "onu-id": onuID,
796 "uni-id": uniID,
797 "device-id": f.deviceHandler.device.Id,
798 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530799
Manikkaraj kb1d51442019-07-23 10:41:02 -0400800 // Check tech profile instance already exists for derived port name
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700801 techProfileInstance, _ := f.techprofile.GetTPInstance(ctx, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000802 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000803 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530804 log.Fields{
805 "path": tpPath,
806 "device-id": f.deviceHandler.device.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700807 techProfileInstance, err = f.techprofile.CreateTechProfileInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000808 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530809 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000810 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530811 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700812 "err": err,
Shrey Baid26912972020-04-16 21:02:31 +0530813 "tp-id": TpID,
814 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000815 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530816 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400817 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700818 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400819 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530820 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000821 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530822 log.Fields{
823 "uni": uni,
824 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530825 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530826 }
Gamze Abakafee36392019-10-03 11:17:24 +0000827
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700828 switch tpInst := techProfileInstance.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700829 case *tp_pb.TechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700830 if UsMeterID != 0 {
831 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
832 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
833 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000834 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700835 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700836 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700837 "onu-id": onuID,
838 "uni-id": uniID,
839 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700840 "meter-id": UsMeterID,
841 "device-id": f.deviceHandler.device.Id})
842 return 0, nil, nil
843 }
844 }
845 if DsMeterID != 0 {
846 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
847 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
848 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000849 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700850 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700851 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700852 "onu-id": onuID,
853 "uni-id": uniID,
854 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700855 "meter-id": DsMeterID,
856 "device-id": f.deviceHandler.device.Id})
857 return 0, nil, nil
858 }
859 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700860 allocID := tpInst.UsScheduler.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700861 for _, gem := range tpInst.UpstreamGemPortAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700862 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700863 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700864 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000865
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700866 if tpInstanceExists {
867 return allocID, gemPortIDs, techProfileInstance
868 }
869
870 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700871 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700872 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000873 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700874 log.Fields{
Matteo Scandolo84585372021-03-18 14:21:22 -0700875 "intf-id": intfID,
876 "onu-id": onuID,
877 "uni-id": uniID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700878 "alloc-ids": allocIDs,
879 "gemports": allgemPortIDs,
880 "device-id": f.deviceHandler.device.Id})
881 // Send Tconts and GEM ports to KV store
882 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530883 return allocID, gemPortIDs, techProfileInstance
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700884 case *openoltpb2.EponTechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700885 // CreateSchedulerQueues for EPON needs to be implemented here
886 // when voltha-protos for EPON is completed.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700887 allocID := tpInst.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700888 for _, gem := range tpInst.UpstreamQueueAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700889 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700890 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700891 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700892
893 if tpInstanceExists {
894 return allocID, gemPortIDs, techProfileInstance
895 }
896
897 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700898 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700899 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000900 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700901 log.Fields{
902 "alloc-ids": allocIDs,
903 "gemports": allgemPortIDs,
904 "device-id": f.deviceHandler.device.Id})
905 // Send Tconts and GEM ports to KV store
906 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
907 return allocID, gemPortIDs, techProfileInstance
908 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000909 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700910 log.Fields{
911 "tpInst": tpInst})
912 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530913 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530914}
915
npujarec5762e2020-01-01 14:08:48 +0530916func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530917
Neha Sharma96b7bf22020-06-15 10:37:32 +0000918 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530919 log.Fields{
920 "intf-id": intfID,
921 "onu-id": onuID,
922 "uni-id": uniID,
923 "alloc-id": allocID,
924 "gemport-ids": gemPortIDs,
925 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530926 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530927 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000928 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 +0530929 }
npujarec5762e2020-01-01 14:08:48 +0530930 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000931 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 +0530932 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700933
Neha Sharma96b7bf22020-06-15 10:37:32 +0000934 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 -0400935 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530936 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400937 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530938}
939
Neha Sharma96b7bf22020-06-15 10:37:32 +0000940func (f *OpenOltFlowMgr) populateTechProfilePerPonPort(ctx context.Context) error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000941 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530942 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000943 for _, intfID := range techRange.IntfIds {
Girish Gowdra4c3d4602021-07-22 16:33:37 -0700944 var err error
945 f.techprofile, err = tp.NewTechProfile(ctx, f.resourceMgr.PonRsrMgr, f.resourceMgr.PonRsrMgr.Backend,
946 f.resourceMgr.PonRsrMgr.Address, f.deviceHandler.cm.Backend.PathPrefix)
947 if err != nil || f.techprofile == nil {
948 logger.Errorw(ctx, "failed-to-allocate-to-techprofile-for-pon-port", log.Fields{"intfID": intfID, "err": err})
949 return fmt.Errorf("failed-to-allocate-tech-profile-for-pon-port--pon-%v-err-%v", intfID, err)
950 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400951 tpCount++
Neha Sharma96b7bf22020-06-15 10:37:32 +0000952 logger.Debugw(ctx, "init-tech-profile-done",
Shrey Baid26912972020-04-16 21:02:31 +0530953 log.Fields{
954 "intf-id": intfID,
955 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530956 }
957 }
958 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400959 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530960 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530961 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800962 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530963 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
964 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530965 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000966 logger.Infow(ctx, "populated-techprofile-for-ponports-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530967 log.Fields{
968 "numofTech": tpCount,
969 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
970 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530971 return nil
972}
973
Gamze Abaka7650be62021-02-26 10:50:36 +0000974func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
975 flowContext.classifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000976 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530977 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000978 "uplinkClassifier": flowContext.classifier,
979 "uplinkAction": flowContext.action})
980 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
Manikkaraj k884c1242019-04-11 16:26:42 +0530981 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530982}
983
Gamze Abaka7650be62021-02-26 10:50:36 +0000984func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
985 downlinkClassifier := flowContext.classifier
986 downlinkAction := flowContext.action
987
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700988 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000989 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530990 log.Fields{
991 "downlinkClassifier": downlinkClassifier,
992 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400993 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
994 if vlan, exists := downlinkClassifier[VlanVid]; exists {
995 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700996 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Gamze Abaka7650be62021-02-26 10:50:36 +0000997 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, flowContext.intfID, flowContext.onuID, flowContext.uniID) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000998 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530999 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +00001000 "flow": flowContext.logicalFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301001 "device-id": f.deviceHandler.device.Id,
Gamze Abaka7650be62021-02-26 10:50:36 +00001002 "onu-id": flowContext.onuID,
1003 "intf-id": flowContext.intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001004 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -04001005 }
1006 }
1007 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301008 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001009
Manikkaraj k884c1242019-04-11 16:26:42 +05301010 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001011 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -04001012 // vlan_vid is a uint32. must be type asserted as such or conversion fails
1013 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +05301014 if ok {
1015 downlinkAction[VlanVid] = dlClVid & 0xfff
1016 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +05301017 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301018 "reason": "failed-to-convert-vlanid-classifier",
1019 "vlan-id": VlanVid,
1020 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +05301021 }
1022
Gamze Abaka7650be62021-02-26 10:50:36 +00001023 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301024}
1025
Gamze Abaka7650be62021-02-26 10:50:36 +00001026func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001027
Gamze Abaka7650be62021-02-26 10:50:36 +00001028 intfID := flowContext.intfID
1029 onuID := flowContext.onuID
1030 uniID := flowContext.uniID
1031 classifier := flowContext.classifier
1032 action := flowContext.action
1033 allocID := flowContext.allocID
1034 gemPortID := flowContext.gemPortID
1035 tpID := flowContext.tpID
1036 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001037 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301038 log.Fields{
1039 "intf-id": intfID,
1040 "onu-id": onuID,
1041 "uni-id": uniID,
1042 "device-id": f.deviceHandler.device.Id,
1043 "classifier": classifier,
1044 "action": action,
1045 "direction": direction,
1046 "alloc-id": allocID,
1047 "gemport-id": gemPortID,
1048 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001049
1050 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001051 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301052 log.Fields{
1053 "device-id": f.deviceHandler.device.Id,
1054 "intf-id": intfID,
1055 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001056 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301057 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001058 classifierProto, err := makeOpenOltClassifierField(classifier)
1059 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301060 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301061 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001062 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301063 log.Fields{
1064 "classifier": *classifierProto,
1065 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001066 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001067 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301068 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301069 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001070 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301071 log.Fields{
1072 "action": *actionProto,
1073 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001074 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301075 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301076 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001077 log.Fields{
1078 "classifier": classifier,
1079 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301080 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001081 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301082 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001083
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001084 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001085 OnuId: int32(onuID),
1086 UniId: int32(uniID),
1087 FlowId: logicalFlow.Id,
1088 FlowType: direction,
1089 AllocId: int32(allocID),
1090 NetworkIntfId: int32(networkIntfID),
1091 GemportId: int32(gemPortID),
1092 Classifier: classifierProto,
1093 Action: actionProto,
1094 Priority: int32(logicalFlow.Priority),
1095 Cookie: logicalFlow.Cookie,
1096 PortNo: flowContext.portNo,
1097 TechProfileId: tpID,
1098 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1099 PbitToGemport: flowContext.pbitToGem,
1100 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001101 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001102 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001103 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301104 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001105 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301106 log.Fields{"direction": direction,
1107 "device-id": f.deviceHandler.device.Id,
1108 "flow": flow,
1109 "intf-id": intfID,
1110 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001111
David K. Bainbridge794735f2020-02-11 21:01:37 -08001112 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301113}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001114
Gamze Abaka7650be62021-02-26 10:50:36 +00001115func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1116
1117 intfID := flowContext.intfID
1118 onuID := flowContext.onuID
1119 uniID := flowContext.uniID
1120 logicalFlow := flowContext.logicalFlow
1121 classifier := flowContext.classifier
1122 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301123
Neha Sharma96b7bf22020-06-15 10:37:32 +00001124 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301125 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301126 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001127 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301128 "action": action,
1129 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001130 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301131 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301132
1133 // Clear the action map
1134 for k := range action {
1135 delete(action, k)
1136 }
1137
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001138 action[TrapToHost] = true
1139 classifier[UDPSrc] = uint32(68)
1140 classifier[UDPDst] = uint32(67)
1141 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301142
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001143 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001144 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301145 log.Fields{
1146 "device-id": f.deviceHandler.device.Id,
1147 "intf-id": intfID,
1148 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001149 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301150 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301151
Neha Sharma96b7bf22020-06-15 10:37:32 +00001152 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301153 log.Fields{
1154 "ul_classifier": classifier,
1155 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001156 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301157 "intf-id": intfID,
1158 "onu-id": onuID,
1159 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301160
David K. Bainbridge794735f2020-02-11 21:01:37 -08001161 classifierProto, err := makeOpenOltClassifierField(classifier)
1162 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301163 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301164 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001165 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001166 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001167 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301168 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301169 }
1170
David K. Bainbridge794735f2020-02-11 21:01:37 -08001171 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001172 OnuId: int32(onuID),
1173 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001174 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001175 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001176 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001177 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001178 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301179 Classifier: classifierProto,
1180 Action: actionProto,
1181 Priority: int32(logicalFlow.Priority),
1182 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001183 PortNo: flowContext.portNo,
1184 TechProfileId: flowContext.tpID,
1185 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1186 PbitToGemport: flowContext.pbitToGem,
1187 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001188 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001189 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001190 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001191 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001192 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301193 log.Fields{
1194 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001195 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301196 "intf-id": intfID,
1197 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301198
David K. Bainbridge794735f2020-02-11 21:01:37 -08001199 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301200}
1201
Esin Karamanae41e2b2019-12-17 18:13:13 +00001202//addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001203func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1204 delete(flowContext.classifier, VlanVid)
1205 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001206}
1207
1208//addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001209func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1210
1211 intfID := flowContext.intfID
1212 onuID := flowContext.onuID
1213 uniID := flowContext.uniID
1214 logicalFlow := flowContext.logicalFlow
1215 classifier := flowContext.classifier
1216 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001217
Neha Sharma96b7bf22020-06-15 10:37:32 +00001218 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001219 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301220 return olterrors.NewErrNotFound("nni-interface-id",
1221 log.Fields{
1222 "classifier": classifier,
1223 "action": action,
1224 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001225 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001226 }
1227
1228 // Clear the action map
1229 for k := range action {
1230 delete(action, k)
1231 }
1232
1233 action[TrapToHost] = true
1234 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001235
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001236 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001237 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001238 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001239 }
1240
Neha Sharma96b7bf22020-06-15 10:37:32 +00001241 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301242 log.Fields{
1243 "ul_classifier": classifier,
1244 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001245 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301246 "device-id": f.deviceHandler.device.Id,
1247 "intf-id": intfID,
1248 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001249
David K. Bainbridge794735f2020-02-11 21:01:37 -08001250 classifierProto, err := makeOpenOltClassifierField(classifier)
1251 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301252 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001253 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001254 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301255 log.Fields{
1256 "classifier": *classifierProto,
1257 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001258 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001259 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301260 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "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 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001264 OnuId: int32(onuID),
1265 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001266 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001267 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001268 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001269 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001270 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001271 Classifier: classifierProto,
1272 Action: actionProto,
1273 Priority: int32(logicalFlow.Priority),
1274 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001275 PortNo: flowContext.portNo,
1276 TechProfileId: flowContext.tpID,
1277 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1278 PbitToGemport: flowContext.pbitToGem,
1279 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001280 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001281
David K. Bainbridge794735f2020-02-11 21:01:37 -08001282 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001283 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": flow, "device-id": f.deviceHandler.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001284 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001285
David K. Bainbridge794735f2020-02-11 21:01:37 -08001286 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001287}
1288
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001289// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001290func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1291 intfID := flowContext.intfID
1292 onuID := flowContext.onuID
1293 uniID := flowContext.uniID
1294 portNo := flowContext.portNo
1295 allocID := flowContext.allocID
1296 gemPortID := flowContext.gemPortID
1297 logicalFlow := flowContext.logicalFlow
1298 classifier := flowContext.classifier
1299 action := flowContext.action
1300
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001301 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301302 log.Fields{
1303 "intf-id": intfID,
1304 "onu-id": onuID,
1305 "port-no": portNo,
1306 "alloc-id": allocID,
1307 "gemport-id": gemPortID,
1308 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001309 "flow": logicalFlow,
1310 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301311
1312 uplinkClassifier := make(map[string]interface{})
1313 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301314
manikkaraj kbf256be2019-03-25 00:13:48 +05301315 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001316 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001317 uplinkClassifier[PacketTagType] = SingleTag
1318 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001319 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301320 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001321 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001322 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001323 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301324 "device-id": f.deviceHandler.device.Id,
1325 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001326 "intf-id": intfID,
1327 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001328 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301329 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001330 //Add Uplink EthType Flow
1331 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301332 log.Fields{
1333 "ul_classifier": uplinkClassifier,
1334 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001335 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301336 "device-id": f.deviceHandler.device.Id,
1337 "intf-id": intfID,
1338 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301339
David K. Bainbridge794735f2020-02-11 21:01:37 -08001340 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1341 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301342 return olterrors.NewErrInvalidValue(log.Fields{
1343 "classifier": uplinkClassifier,
1344 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301345 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001346 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301347 log.Fields{
1348 "classifier": *classifierProto,
1349 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001350 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001351 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301352 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301353 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001354 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301355 log.Fields{
1356 "action": *actionProto,
1357 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001358 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301359 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301360 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001361 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301362 "action": action,
1363 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001364 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301365 }
1366
David K. Bainbridge794735f2020-02-11 21:01:37 -08001367 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001368 OnuId: int32(onuID),
1369 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001370 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001371 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001372 AllocId: int32(allocID),
1373 NetworkIntfId: int32(networkIntfID),
1374 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301375 Classifier: classifierProto,
1376 Action: actionProto,
1377 Priority: int32(logicalFlow.Priority),
1378 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001379 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001380 TechProfileId: flowContext.tpID,
1381 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1382 PbitToGemport: flowContext.pbitToGem,
1383 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001384 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001385 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001386 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001387 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001388 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301389 log.Fields{
1390 "device-id": f.deviceHandler.device.Id,
1391 "onu-id": onuID,
1392 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001393 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301394 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001395
David K. Bainbridge794735f2020-02-11 21:01:37 -08001396 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301397}
1398
David K. Bainbridge794735f2020-02-11 21:01:37 -08001399func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001400 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001401
1402 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1403 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1404 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001405 if vlanID != ReservedVlan {
1406 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001407 classifier.OVid = vid
1408 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301409 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001410 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1411 vid := uint32(metadata)
1412 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001413 classifier.IVid = vid
1414 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301415 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301416 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001417 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301418 classifier.OPbits = vlanPcp
1419 } else {
1420 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301421 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001422 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1423 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1424 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1425 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001426 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001427 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1428 classifier.PktTagType = pktTagType
1429
1430 switch pktTagType {
1431 case SingleTag:
1432 case DoubleTag:
1433 case Untagged:
1434 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001435 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301436 }
1437 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001438 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301439}
1440
Gamze Abaka724d0852020-03-18 12:10:24 +00001441func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001442 var actionCmd openoltpb2.ActionCmd
1443 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301444 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001445 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301446 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001447 if _, ok := actionInfo[VlanPcp]; ok {
1448 action.Cmd.RemarkInnerPbits = true
1449 action.IPbits = actionInfo[VlanPcp].(uint32)
1450 if _, ok := actionInfo[VlanVid]; ok {
1451 action.Cmd.TranslateInnerTag = true
1452 action.IVid = actionInfo[VlanVid].(uint32)
1453 }
1454 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001455 } else if _, ok := actionInfo[PushVlan]; ok {
1456 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301457 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001458 if _, ok := actionInfo[VlanPcp]; ok {
1459 action.OPbits = actionInfo[VlanPcp].(uint32)
1460 action.Cmd.RemarkOuterPbits = true
1461 if _, ok := classifierInfo[VlanVid]; ok {
1462 action.IVid = classifierInfo[VlanVid].(uint32)
1463 action.Cmd.TranslateInnerTag = true
1464 }
1465 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001466 } else if _, ok := actionInfo[TrapToHost]; ok {
1467 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301468 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001469 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301470 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001471 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301472}
1473
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001474// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001475func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001476 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301477}
1478
Gamze Abakafee36392019-10-03 11:17:24 +00001479// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdra197acc12021-08-16 10:59:45 -07001480// We also force release scheduler and queues associated with the tp instance. Theoretically there could be
1481// an issue if the upstream scheduler (DBA) is shared across multiple UNI and we force release it, given that
1482// this function is only meant to clean up TP instances of a given UNI. But in practicality this routine
1483// is only meant to be called when the clean up of resource for the whole ONU is taking place.
1484// The reason for introducing the force cleanup of scheduler and queues (on the OLT) was introduced here
1485// because it was observed that if the ONU device was deleted too soon after the flows were
1486// unprovisioned on that ONU, the scheduler and queue removal pertinent to that ONU would remain
1487// uncleaned on the OLT. So we force clean up here and ignore any error that OLT returns during the
1488// force cleanup (possible if the OLT has already cleared those resources).
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001489func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301490 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001491 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1492
Gamze Abakafee36392019-10-03 11:17:24 +00001493 for _, tpID := range tpIDList {
Girish Gowdra197acc12021-08-16 10:59:45 -07001494
1495 // Force cleanup scheduler/queues -- start
1496 uniPortNum := MkUniPortNum(ctx, intfID, onuID, uniID)
1497 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1498 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
1499 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1500 if err != nil || tpInst == nil { // This should not happen, something wrong in KV backend transaction
1501 logger.Warnw(ctx, "tech-profile-not-in-kv-store",
1502 log.Fields{
1503 "tp-id": tpID,
1504 "path": tpPath})
1505 }
1506 switch tpInstance := tpInst.(type) {
1507 case *tp_pb.TechProfileInstance:
1508 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1509 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1510 }
1511 // Force cleanup scheduler/queues -- end
1512
1513 // Now remove the tp instance
npujarec5762e2020-01-01 14:08:48 +05301514 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001515 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301516 // return err
1517 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001518 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001519 logger.Debugw(ctx, "tech-profile-instance-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "uniPortName": uniPortName, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001520 }
1521 return nil
1522}
1523
1524// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301525func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001526 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001527 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001528 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001529 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301530 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1531 log.Fields{
1532 "tp-id": tpID,
1533 "uni-port-name": uniPortName,
1534 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001535 }
1536 return nil
1537}
1538
David K. Bainbridge794735f2020-02-11 21:01:37 -08001539func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001540
1541 var intfID uint32
1542 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1543 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1544 */
1545 if deviceFlow.AccessIntfId != -1 {
1546 intfID = uint32(deviceFlow.AccessIntfId)
1547 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001548 // We need to log the valid interface ID.
1549 // For trap-on-nni flows, the access_intf_id is invalid (-1), so choose the network_intf_id.
Daniele Rossi22db98e2019-07-11 11:50:00 +00001550 intfID = uint32(deviceFlow.NetworkIntfId)
1551 }
1552
Neha Sharma96b7bf22020-06-15 10:37:32 +00001553 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301554 "flow": *deviceFlow,
1555 "device-id": f.deviceHandler.device.Id,
1556 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001557 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001558
1559 st, _ := status.FromError(err)
1560 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001561 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001562 "err": err,
1563 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301564 "device-id": f.deviceHandler.device.Id,
1565 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001566 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301567 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001568
1569 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001570 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301571 log.Fields{"err": err,
1572 "device-flow": deviceFlow,
1573 "device-id": f.deviceHandler.device.Id,
1574 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001575 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001576 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001577 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301578 log.Fields{
1579 "flow": *deviceFlow,
1580 "device-id": f.deviceHandler.device.Id,
1581 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001582
1583 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1584 if deviceFlow.AccessIntfId != -1 {
1585 // No need to register the flow if it is a trap on nni flow.
1586 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1587 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1588 return err
1589 }
1590 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001591 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001592}
1593
Neha Sharma96b7bf22020-06-15 10:37:32 +00001594func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1595 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301596 log.Fields{
1597 "flow": *deviceFlow,
1598 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001599 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001600 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001601 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001602 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301603 log.Fields{
1604 "err": err,
1605 "deviceFlow": deviceFlow,
1606 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001607 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001608 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001609 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001610 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001611
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001612 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001613 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001614 "of-flow-id": ofFlowID,
1615 "flow": *deviceFlow,
1616 "device-id": f.deviceHandler.device.Id,
1617 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001618 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301619}
1620
David K. Bainbridge794735f2020-02-11 21:01:37 -08001621func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001622
1623 classifierInfo := make(map[string]interface{})
1624 actionInfo := make(map[string]interface{})
1625
1626 classifierInfo[EthType] = uint32(LldpEthType)
1627 classifierInfo[PacketTagType] = Untagged
1628 actionInfo[TrapToHost] = true
1629
1630 // LLDP flow is installed to trap LLDP packets on the NNI port.
1631 // We manage flow_id resource pool on per PON port basis.
1632 // Since this situation is tricky, as a hack, we pass the NNI port
1633 // index (network_intf_id) as PON port Index for the flow_id resource
1634 // pool. Also, there is no ONU Id available for trapping LLDP packets
1635 // on NNI port, use onu_id as -1 (invalid)
1636 // ****************** CAVEAT *******************
1637 // This logic works if the NNI Port Id falls within the same valid
1638 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1639 // we need to have a re-look at this.
1640 // *********************************************
1641
1642 var onuID = -1
1643 var uniID = -1
1644 var gemPortID = -1
1645
Neha Sharma96b7bf22020-06-15 10:37:32 +00001646 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001647 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301648 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001649 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001650 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001651 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001652 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001653 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001654
David K. Bainbridge794735f2020-02-11 21:01:37 -08001655 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1656 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301657 return olterrors.NewErrInvalidValue(
1658 log.Fields{
1659 "classifier": classifierInfo,
1660 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001661 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001662 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301663 log.Fields{
1664 "classifier": *classifierProto,
1665 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001666 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001667 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301668 return olterrors.NewErrInvalidValue(
1669 log.Fields{
1670 "action": actionInfo,
1671 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001672 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001673 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301674 log.Fields{
1675 "action": *actionProto,
1676 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001677
1678 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1679 OnuId: int32(onuID), // OnuId not required
1680 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001681 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001682 FlowType: Downstream,
1683 NetworkIntfId: int32(networkInterfaceID),
1684 GemportId: int32(gemPortID),
1685 Classifier: classifierProto,
1686 Action: actionProto,
1687 Priority: int32(flow.Priority),
1688 Cookie: flow.Cookie,
1689 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001690 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001691 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301692 log.Fields{
1693 "flow": downstreamflow,
1694 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001695 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001696 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301697 log.Fields{
1698 "device-id": f.deviceHandler.device.Id,
1699 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001700 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001701
David K. Bainbridge794735f2020-02-11 21:01:37 -08001702 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301703}
1704
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001705func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1706 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001707}
1708
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001709//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001710func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001711 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1712 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1713 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001714 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301715 log.Fields{
1716 "intf-id": intfID,
1717 "onu-id": onuID,
1718 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001719 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001720 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301721 return nil, olterrors.NewErrNotFound("onu-child-device",
1722 log.Fields{
1723 "onu-id": onuID,
1724 "intf-id": intfID,
1725 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001726 }
1727 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1728 //better to ad the device to cache here.
1729 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1730 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001731 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301732 log.Fields{
1733 "intf-id": intfID,
1734 "onu-id": onuID,
1735 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001736 }
1737
1738 return onuDev.(*OnuDevice), nil
1739}
1740
1741//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001742func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1743 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301744 log.Fields{
1745 "pon-port": intfID,
1746 "onu-id": onuID,
1747 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001748 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001749 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001750 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301751 return nil, olterrors.NewErrNotFound("onu",
1752 log.Fields{
1753 "interface-id": parentPortNo,
1754 "onu-id": onuID,
1755 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001756 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301757 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001758 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301759 log.Fields{
1760 "device-id": f.deviceHandler.device.Id,
1761 "child_device_id": onuDevice.Id,
1762 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301763 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301764}
1765
Neha Sharma96b7bf22020-06-15 10:37:32 +00001766func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1767 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301768 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001769 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301770 log.Fields{
1771 "intf-id": intfID,
1772 "onu-id": onuID,
1773 "uni-id": uniID,
1774 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001775 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301776 }
1777
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001778 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpInstancePath: tpPath, GemPortId: gemPortID}
1779 logger.Infow(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301780 log.Fields{
1781 "msg": *delGemPortMsg,
1782 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001783 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301784 delGemPortMsg,
1785 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001786 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001787 onuDev.deviceType,
1788 onuDev.deviceID,
1789 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301790 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1791 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001792 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301793 "to-adapter": onuDev.deviceType,
1794 "onu-id": onuDev.deviceID,
1795 "proxyDeviceID": onuDev.proxyDeviceID,
1796 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301797 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001798 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301799 log.Fields{
1800 "msg": delGemPortMsg,
1801 "from-adapter": f.deviceHandler.device.Type,
1802 "to-adapter": onuDev.deviceType,
1803 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301804 return nil
1805}
1806
Neha Sharma96b7bf22020-06-15 10:37:32 +00001807func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1808 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301809 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001810 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301811 log.Fields{
1812 "intf-id": intfID,
1813 "onu-id": onuID,
1814 "uni-id": uniID,
1815 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001816 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301817 }
1818
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001819 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpInstancePath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001820 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301821 log.Fields{
1822 "msg": *delTcontMsg,
1823 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001824 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301825 delTcontMsg,
1826 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001827 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001828 onuDev.deviceType,
1829 onuDev.deviceID,
1830 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301831 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1832 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001833 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301834 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1835 "proxyDeviceID": onuDev.proxyDeviceID,
1836 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301837 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001838 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301839 log.Fields{
1840 "msg": delTcontMsg,
1841 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301842 return nil
1843}
1844
Girish Gowdrac3037402020-01-22 20:29:53 +05301845// Once the gemport is released for a given onu, it also has to be cleared from local cache
1846// which was used for deriving the gemport->logicalPortNo during packet-in.
1847// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1848// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001849func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001850 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301851 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001852 "gem-port-id": gemPortID,
1853 "intf-id": intfID,
1854 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001855 "device-id": f.deviceHandler.device.Id})
1856 f.onuGemInfoLock.RLock()
1857 onugem, ok := f.onuGemInfoMap[onuID]
1858 f.onuGemInfoLock.RUnlock()
1859 if !ok {
1860 logger.Warnw(ctx, "onu gem info already cleared from cache", log.Fields{
1861 "gem-port-id": gemPortID,
1862 "intf-id": intfID,
1863 "onu-id": onuID,
1864 "device-id": f.deviceHandler.device.Id})
1865 return
1866 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001867deleteLoop:
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001868 for j, gem := range onugem.GemPorts {
1869 // If the gemport is found, delete it from local cache.
1870 if gem == gemPortID {
1871 onugem.GemPorts = append(onugem.GemPorts[:j], onugem.GemPorts[j+1:]...)
1872 f.onuGemInfoLock.Lock()
1873 f.onuGemInfoMap[onuID] = onugem
1874 f.onuGemInfoLock.Unlock()
1875 logger.Infow(ctx, "removed-gemport-from-local-cache",
1876 log.Fields{
1877 "intf-id": intfID,
1878 "onu-id": onuID,
1879 "deletedgemport-id": gemPortID,
1880 "gemports": onugem.GemPorts,
1881 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001882 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301883 }
1884 }
1885}
1886
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301887//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001888// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001889func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Girish Gowdra82c80982021-03-26 16:22:02 -07001890 gemPortID int32, flowID uint64, portNum uint32, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001891
Girish Gowdraa482f272021-03-24 23:04:19 -07001892 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
1893 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001894 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1895 log.Fields{
1896 "tpPath": tpPath,
1897 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001898
1899 used := f.isGemPortUsedByAnotherFlow(uint32(gemPortID))
1900
1901 if used {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001902 f.gemToFlowIDsKey.RLock()
1903 flowIDs := f.gemToFlowIDs[uint32(gemPortID)]
1904 f.gemToFlowIDsKey.RUnlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001905
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001906 for i, flowIDinMap := range flowIDs {
1907 if flowIDinMap == flowID {
1908 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001909 f.gemToFlowIDsKey.Lock()
1910 f.gemToFlowIDs[uint32(gemPortID)] = flowIDs
1911 f.gemToFlowIDsKey.Unlock()
1912 // everytime gemToFlowIDs cache is updated the same should be updated
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001913 // in kv store by calling UpdateFlowIDsForGem
Girish Gowdraa482f272021-03-24 23:04:19 -07001914 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, intfID, uint32(gemPortID), flowIDs); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001915 return err
1916 }
1917 break
1918 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001919 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001920 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1921 log.Fields{
1922 "gemport-id": gemPortID,
1923 "usedByFlows": flowIDs,
1924 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -07001925
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001926 return nil
1927 }
1928 logger.Debugf(ctx, "gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
Girish Gowdraa482f272021-03-24 23:04:19 -07001929 f.deleteGemPortFromLocalCache(ctx, intfID, uint32(onuID), uint32(gemPortID))
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001930 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, intfID, uint32(onuID), uint32(gemPortID)) // ignore error and proceed.
1931 //everytime an entry is deleted from gemToFlowIDs cache, the same should be updated in kv as well
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001932 // by calling DeleteFlowIDsForGem
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001933 f.gemToFlowIDsKey.Lock()
1934 delete(f.gemToFlowIDs, uint32(gemPortID))
1935 f.gemToFlowIDsKey.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001936
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001937 f.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, uint32(gemPortID))
1938
1939 f.resourceMgr.FreeGemPortID(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001940
Mahir Gunyel199570a2021-07-04 15:39:36 -07001941 //First remove TCONT from child if needed. Then remove the GEM.
1942 //It is expected from child to clean ani side conf if all GEMs of TP are deleted.
1943 //Before this, ensure that the related TCONT deletions are informed to child.
1944 //Refer to VOL-4215.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001945 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1946 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1947 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1948 log.Fields{
1949 "tp-id": tpID,
1950 "path": tpPath}, err)
1951 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001952 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001953 case *tp_pb.TechProfileInstance:
Gamze Abakacb0e6772021-06-10 08:32:12 +00001954 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst, uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001955 if !ok {
Girish Gowdraa482f272021-03-24 23:04:19 -07001956 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001957 logger.Warn(ctx, err)
1958 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001959 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001960 logger.Warn(ctx, err)
1961 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001962 if err := f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001963 logger.Warn(ctx, err)
1964 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001965 if err := f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001966 logger.Warn(ctx, err)
1967 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001968 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001969 case *tp_pb.EponTechProfileInstance:
Girish Gowdraa482f272021-03-24 23:04:19 -07001970 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001971 logger.Warn(ctx, err)
1972 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001973 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001974 logger.Warn(ctx, err)
1975 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001976 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001977 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001978 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001979 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05301980 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07001981 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05301982 "onu-id": onuID,
1983 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001984 "device-id": f.deviceHandler.device.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001985 "alloc-id": techprofileInst.AllocId})
Gamze Abakafee36392019-10-03 11:17:24 +00001986 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001987 default:
1988 logger.Errorw(ctx, "error-unknown-tech",
1989 log.Fields{
1990 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001991 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001992
Mahir Gunyel199570a2021-07-04 15:39:36 -07001993 // Delete the gem port on the ONU. Send Gem Removal After TCONT removal.
1994 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
1995 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
1996 log.Fields{
1997 "err": err,
1998 "intfID": intfID,
1999 "onu-id": onuID,
2000 "uni-id": uniID,
2001 "device-id": f.deviceHandler.device.Id,
2002 "gemport-id": gemPortID})
2003 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302004 return nil
2005}
2006
David K. Bainbridge794735f2020-02-11 21:01:37 -08002007// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002008func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002009 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302010 log.Fields{
2011 "flowDirection": flowDirection,
2012 "flow": *flow,
2013 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002014
2015 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002016 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002017 }
2018
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302019 classifierInfo := make(map[string]interface{})
2020
Neha Sharma96b7bf22020-06-15 10:37:32 +00002021 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302022 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002023 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002024 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302025 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302026
David K. Bainbridge794735f2020-02-11 21:01:37 -08002027 onuID := int32(onu)
2028 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002029 tpID, err := getTpIDFromFlow(ctx, flow)
2030 if err != nil {
2031 return olterrors.NewErrNotFound("tp-id",
2032 log.Fields{
2033 "flow": flow,
2034 "intf-id": Intf,
2035 "onu-id": onuID,
2036 "uni-id": uniID,
2037 "device-id": f.deviceHandler.device.Id}, err)
2038 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302039
2040 for _, field := range flows.GetOfbFields(flow) {
2041 if field.Type == flows.IP_PROTO {
2042 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002043 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302044 }
2045 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002046 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302047 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002048 "flow-id": flow.Id,
2049 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302050 "onu-id": onuID,
2051 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302052
2053 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2054 onuID = -1
2055 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002056 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
2057 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002058 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002059 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002060 log.Fields{
2061 "port-number": inPort,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002062 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002063 return err
David K. Bainbridge794735f2020-02-11 21:01:37 -08002064 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302065 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002066
2067 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
2068 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002069 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2070 return err
2071 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002072
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002073 f.flowIDToGemsLock.Lock()
2074 gems, ok := f.flowIDToGems[flow.Id]
2075 if !ok {
2076 logger.Errorw(ctx, "flow-id-to-gem-map-not-found", log.Fields{"flowID": flow.Id})
2077 f.flowIDToGemsLock.Unlock()
2078 return olterrors.NewErrNotFound("flow-id-to-gem-map-not-found", log.Fields{"flowID": flow.Id}, nil)
2079 }
2080 copyOfGems := make([]uint32, len(gems))
2081 _ = copy(copyOfGems, gems)
2082 // Delete the flow-id to gemport list entry from the map now the flow is deleted.
2083 delete(f.flowIDToGems, flow.Id)
2084 f.flowIDToGemsLock.Unlock()
2085
2086 logger.Debugw(ctx, "gems-to-be-cleared", log.Fields{"gems": copyOfGems})
2087 for _, gem := range copyOfGems {
2088 if err = f.clearResources(ctx, Intf, onuID, uniID, int32(gem), flow.Id, portNum, tpID); err != nil {
Girish Gowdra0aca4982021-01-04 12:44:27 -08002089 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002090 "flow-id": flow.Id,
2091 "device-id": f.deviceHandler.device.Id,
2092 "onu-id": onuID,
2093 "intf": Intf,
2094 "gem": gem,
2095 "err": err,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002096 })
2097 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302098 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302099 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002100
Girish Gowdra82c80982021-03-26 16:22:02 -07002101 // Decrement reference count for the meter associated with the given <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
2102 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, Intf, uint32(onuID), uint32(uniID), tpID, false); err != nil {
2103 return err
2104 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002105 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002106}
2107
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002108//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002109func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002110
Matteo Scandolof16389e2021-05-18 00:47:08 +00002111 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302112 var direction string
2113 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002114
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302115 for _, action := range flows.GetActions(flow) {
2116 if action.Type == flows.OUTPUT {
2117 if out := action.GetOutput(); out != nil {
2118 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002119 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302120 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002121 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002122 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002123 }
2124 }
2125 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002126
2127 if flows.HasGroup(flow) {
2128 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002129 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Esin Karamanccb714b2019-11-29 15:02:06 +00002130 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302131 direction = Upstream
2132 } else {
2133 direction = Downstream
2134 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302135
Girish Gowdracefae192020-03-19 18:14:10 -07002136 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002137 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002138
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002139 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002140}
2141
Esin Karamanae41e2b2019-12-17 18:13:13 +00002142//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2143func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2144 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2145 if ethType, ok := classifierInfo[EthType]; ok {
2146 if ethType.(uint32) == IPv4EthType {
2147 if ipProto, ok := classifierInfo[IPProto]; ok {
2148 if ipProto.(uint32) == IgmpProto {
2149 return true
2150 }
2151 }
2152 }
2153 }
2154 }
2155 return false
2156}
2157
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002158// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
2159func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *voltha.OfpFlowStats, addFlow bool, flowMetadata *voltha.FlowMetadata) error {
2160 // Step1 : Fill flowControlBlock
2161 // Step2 : Push the flowControlBlock to ONU channel
2162 // Step3 : Wait on response channel for response
2163 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002164 startTime := time.Now()
2165 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002166 errChan := make(chan error)
2167 flowCb := flowControlBlock{
2168 ctx: ctx,
2169 addFlow: addFlow,
2170 flow: flow,
2171 flowMetadata: flowMetadata,
2172 errChan: &errChan,
2173 }
2174 inPort, outPort := getPorts(flow)
2175 var onuID uint32
2176 if inPort != InvalidPort && outPort != InvalidPort {
2177 _, _, onuID, _ = ExtractAccessFromFlow(inPort, outPort)
2178 }
2179 // inPort or outPort is InvalidPort for trap-from-nni flows.
2180 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2181 // Send the flowCb on the ONU flow channel
2182 f.incomingFlows[onuID] <- flowCb
2183 // Wait on the channel for flow handlers return value
2184 err := <-errChan
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002185 logger.Infow(ctx, "process-flow--received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002186 return err
2187}
2188
2189// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2190// Each incoming flow is processed in a synchronous manner, i.e., the flow is processed to completion before picking another
2191func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(subscriberFlowChannel chan flowControlBlock) {
2192 for {
2193 // block on the channel to receive an incoming flow
2194 // process the flow completely before proceeding to handle the next flow
2195 flowCb := <-subscriberFlowChannel
2196 if flowCb.addFlow {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002197 logger.Info(flowCb.ctx, "adding-flow-start")
2198 startTime := time.Now()
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002199 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002200 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002201 // Pass the return value over the return channel
2202 *flowCb.errChan <- err
2203 } else {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002204 logger.Info(flowCb.ctx, "removing-flow-start")
2205 startTime := time.Now()
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002206 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002207 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002208 // Pass the return value over the return channel
2209 *flowCb.errChan <- err
2210 }
2211 }
2212}
2213
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002214// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302215// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002216func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002217 classifierInfo := make(map[string]interface{})
2218 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002219 var UsMeterID uint32
2220 var DsMeterID uint32
2221
Neha Sharma96b7bf22020-06-15 10:37:32 +00002222 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302223 log.Fields{
2224 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002225 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002226 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002227
Neha Sharma96b7bf22020-06-15 10:37:32 +00002228 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002229 if err != nil {
2230 // Error logging is already done in the called function
2231 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002232 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302233 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002234
Esin Karamanccb714b2019-11-29 15:02:06 +00002235 if flows.HasGroup(flow) {
2236 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002237 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002238 }
2239
manikkaraj k17652a72019-05-06 09:06:36 -04002240 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002241 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002242 if err != nil {
2243 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002244 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002245 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002246
Neha Sharma96b7bf22020-06-15 10:37:32 +00002247 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302248 log.Fields{
2249 "classifierinfo_inport": classifierInfo[InPort],
2250 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002251 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002252
Humera Kouser94d7a842019-08-25 19:04:32 -04002253 if ethType, ok := classifierInfo[EthType]; ok {
2254 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002255 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002256 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002257 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002258 if ethType.(uint32) == PPPoEDEthType {
2259 if voltha.Port_ETHERNET_NNI == IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
2260 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2261 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2262 }
2263 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002264 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002265 if ipProto, ok := classifierInfo[IPProto]; ok {
2266 if ipProto.(uint32) == IPProtoDhcp {
2267 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302268 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002269 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002270 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002271 }
2272 }
2273 }
2274 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002275 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002276 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002277 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002278 }
A R Karthick1f85b802019-10-11 05:06:05 +00002279
npujarec5762e2020-01-01 14:08:48 +05302280 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002281 // also update flowmgr cache
2282 f.onuGemInfoLock.Lock()
2283 onugem, ok := f.onuGemInfoMap[onuID]
2284 if ok {
2285 found := false
2286 for _, uni := range onugem.UniPorts {
2287 if uni == portNo {
2288 found = true
2289 break
2290 }
2291 }
2292 if !found {
2293 onugem.UniPorts = append(onugem.UniPorts, portNo)
2294 f.onuGemInfoMap[onuID] = onugem
2295 logger.Infow(ctx, "added uni port to onugem cache", log.Fields{"uni": portNo})
2296 }
2297 }
2298 f.onuGemInfoLock.Unlock()
A R Karthick1f85b802019-10-11 05:06:05 +00002299
Neha Sharma96b7bf22020-06-15 10:37:32 +00002300 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002301 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302302 return olterrors.NewErrNotFound("tpid-for-flow",
2303 log.Fields{
2304 "flow": flow,
2305 "intf-id": IntfID,
2306 "onu-id": onuID,
2307 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002308 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002309 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302310 log.Fields{
2311 "tp-id": TpID,
2312 "intf-id": intfID,
2313 "onu-id": onuID,
2314 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002315 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002316 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002317 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002318 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002319 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002320 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002321
2322 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002323 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002324}
Girish Gowdra3d633032019-12-10 16:37:05 +05302325
Esin Karamanccb714b2019-11-29 15:02:06 +00002326// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002327func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002328 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002329 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302330 "classifier-info": classifierInfo,
2331 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002332
Esin Karaman65409d82020-03-18 10:58:18 +00002333 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002334 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002335 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002336 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002337
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002338 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002339
David K. Bainbridge794735f2020-02-11 21:01:37 -08002340 onuID := NoneOnuID
2341 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002342
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002343 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002344 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002345 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002346 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002347 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2348 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002349 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002350 }
2351 groupID := actionInfo[GroupID].(uint32)
2352 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002353 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002354 FlowType: Multicast,
2355 NetworkIntfId: int32(networkInterfaceID),
2356 GroupId: groupID,
2357 Classifier: classifierProto,
2358 Priority: int32(flow.Priority),
2359 Cookie: flow.Cookie}
2360
Kent Hagermane6ff1012020-07-14 15:07:53 -04002361 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002362 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002363 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002364 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002365 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002366 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002367 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002368 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002369 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002370 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002371 //cached group can be removed now
2372 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002373 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002374 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002375 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002376
David K. Bainbridge794735f2020-02-11 21:01:37 -08002377 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002378}
2379
Esin Karaman65409d82020-03-18 10:58:18 +00002380//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2381func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2382 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002383 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002384 if err != nil {
2385 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2386 }
2387 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002388 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002389
2390 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2391 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002392}
2393
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002394//sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002395func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32, tpInst tp_pb.TechProfileInstance) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002396
Neha Sharma96b7bf22020-06-15 10:37:32 +00002397 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302398 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002399 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302400 log.Fields{
2401 "intf-id": intfID,
2402 "onu-id": onuID,
2403 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002404 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302405 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002406 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002407
Neha Sharma96b7bf22020-06-15 10:37:32 +00002408 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002409 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{
2410 UniId: uniID,
2411 TpInstancePath: tpPath,
2412 TechTpInstance: &ic.InterAdapterTechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
2413 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002414 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002415 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
manikkaraj k17652a72019-05-06 09:06:36 -04002416 tpDownloadMsg,
2417 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03002418 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002419 onuDev.deviceType,
2420 onuDev.deviceID,
2421 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002422 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302423 return olterrors.NewErrCommunication("send-techprofile-download-request",
2424 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03002425 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05302426 "to-adapter": onuDev.deviceType,
2427 "onu-id": onuDev.deviceID,
2428 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002429 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002430 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302431 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302432}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002433
Girish Gowdra197acc12021-08-16 10:59:45 -07002434//AddOnuInfoToFlowMgrCacheAndKvStore function adds onu info to cache and kvstore
2435func (f *OpenOltFlowMgr) AddOnuInfoToFlowMgrCacheAndKvStore(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302436
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002437 f.onuGemInfoLock.RLock()
2438 _, ok := f.onuGemInfoMap[onuID]
2439 f.onuGemInfoLock.RUnlock()
Girish Gowdra9602eb42020-09-09 15:50:39 -07002440 // If the ONU already exists in onuGemInfo list, nothing to do
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002441 if ok {
2442 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2443 log.Fields{"onuID": onuID,
2444 "serialNum": serialNum})
2445 return nil
Girish Gowdra9602eb42020-09-09 15:50:39 -07002446 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002447
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002448 onuGemInfo := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2449 f.onuGemInfoLock.Lock()
2450 f.onuGemInfoMap[onuID] = &onuGemInfo
2451 f.onuGemInfoLock.Unlock()
2452 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onuID, onuGemInfo); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002453 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302454 }
Girish Gowdra197acc12021-08-16 10:59:45 -07002455 logger.Infow(ctx, "added-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302456 log.Fields{
2457 "intf-id": intfID,
2458 "onu-id": onuID,
2459 "serial-num": serialNum,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002460 "onu": onuGemInfo,
Shrey Baid26912972020-04-16 21:02:31 +05302461 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002462 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002463}
2464
Girish Gowdra197acc12021-08-16 10:59:45 -07002465//RemoveOnuInfoFromFlowMgrCacheAndKvStore function adds onu info to cache and kvstore
2466func (f *OpenOltFlowMgr) RemoveOnuInfoFromFlowMgrCacheAndKvStore(ctx context.Context, intfID uint32, onuID uint32) error {
2467
2468 f.onuGemInfoLock.Lock()
2469 delete(f.onuGemInfoMap, onuID)
2470 f.onuGemInfoLock.Unlock()
2471
2472 if err := f.resourceMgr.DelOnuGemInfo(ctx, intfID, onuID); err != nil {
2473 return err
2474 }
2475 logger.Infow(ctx, "deleted-onuinfo",
2476 log.Fields{
2477 "intf-id": intfID,
2478 "onu-id": onuID,
2479 "device-id": f.deviceHandler.device.Id})
2480 return nil
2481}
2482
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302483//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302484func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002485
Neha Sharma96b7bf22020-06-15 10:37:32 +00002486 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302487 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002488 "gem-port-id": gemPort,
2489 "intf-id": intfID,
2490 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002491 "device-id": f.deviceHandler.device.Id})
2492 f.onuGemInfoLock.RLock()
2493 onugem, ok := f.onuGemInfoMap[onuID]
2494 f.onuGemInfoLock.RUnlock()
2495 if !ok {
2496 logger.Warnw(ctx, "onu gem info is missing", log.Fields{
2497 "gem-port-id": gemPort,
2498 "intf-id": intfID,
2499 "onu-id": onuID,
2500 "device-id": f.deviceHandler.device.Id})
2501 return
2502 }
2503
2504 if onugem.OnuID == onuID {
2505 // check if gem already exists , else update the cache and kvstore
2506 for _, gem := range onugem.GemPorts {
2507 if gem == gemPort {
2508 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
2509 log.Fields{
2510 "gem": gemPort,
2511 "device-id": f.deviceHandler.device.Id})
2512 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302513 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302514 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002515 onugem.GemPorts = append(onugem.GemPorts, gemPort)
2516 f.onuGemInfoLock.Lock()
2517 f.onuGemInfoMap[onuID] = onugem
2518 f.onuGemInfoLock.Unlock()
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002519 logger.Debugw(ctx, "updated onu gem info from cache", log.Fields{"onugem": onugem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002520 } else {
2521 logger.Warnw(ctx, "mismatched onu id", log.Fields{
2522 "gem-port-id": gemPort,
2523 "intf-id": intfID,
2524 "onu-id": onuID,
2525 "device-id": f.deviceHandler.device.Id})
2526 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302527 }
npujarec5762e2020-01-01 14:08:48 +05302528 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302529 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002530 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302531 log.Fields{
2532 "intf-id": intfID,
2533 "onu-id": onuID,
2534 "gemPort": gemPort,
2535 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002536 return
2537 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002538 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302539 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002540 "gem-port-id": gemPort,
2541 "intf-id": intfID,
2542 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002543 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002544}
2545
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002546//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302547func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002548 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002549
2550 if packetIn.IntfType == "pon" {
2551 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002552 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002553 onuID, uniID := packetIn.OnuId, packetIn.UniId
2554 logger.Debugf(ctx, "retrieved ONU and UNI IDs [%d, %d] by interface:%d, gem:%d", packetIn.OnuId, packetIn.UniId, packetIn.GemportId)
Esin Karamandf392e12020-12-16 13:33:09 +00002555
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002556 if packetIn.PortNo != 0 {
2557 logicalPortNum = packetIn.PortNo
2558 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002559 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002560 }
2561 // 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 +00002562 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002563 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002564 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002565 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002566
2567 if logger.V(log.DebugLevel) {
2568 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2569 log.Fields{
2570 "logical-port-num": logicalPortNum,
2571 "intf-type": packetIn.IntfType,
2572 "packet": hex.EncodeToString(packetIn.Pkt),
2573 })
2574 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002575 return logicalPortNum, nil
2576}
2577
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002578//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002579func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002580 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002581
2582 ctag, priority, err := getCTagFromPacket(ctx, packet)
2583 if err != nil {
2584 return 0, err
2585 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302586
Esin Karaman7fb80c22020-07-16 14:23:33 +00002587 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002588 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002589 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002590 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002591 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302592 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002593 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302594 log.Fields{
2595 "pktinkey": pktInkey,
2596 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002597
2598 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002599 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302600 //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 +00002601 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302602 if err == nil {
2603 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002604 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302605 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002606 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002607 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302608 log.Fields{
2609 "pktinkey": pktInkey,
2610 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302611 return gemPortID, nil
2612 }
2613 }
Shrey Baid26912972020-04-16 21:02:31 +05302614 return uint32(0), olterrors.NewErrNotFound("gem-port",
2615 log.Fields{
2616 "pktinkey": pktInkey,
2617 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002618
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002619}
2620
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002621func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2622 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002623 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002624 classifier[PacketTagType] = DoubleTag
2625 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002626 /* We manage flowId resource pool on per PON port basis.
2627 Since this situation is tricky, as a hack, we pass the NNI port
2628 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002629 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002630 on NNI port, use onu_id as -1 (invalid)
2631 ****************** CAVEAT *******************
2632 This logic works if the NNI Port Id falls within the same valid
2633 range of PON Port Ids. If this doesn't work for some OLT Vendor
2634 we need to have a re-look at this.
2635 *********************************************
2636 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002637 onuID := -1
2638 uniID := -1
2639 gemPortID := -1
2640 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002641 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302642 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302643 return olterrors.NewErrNotFound("nni-intreface-id",
2644 log.Fields{
2645 "classifier": classifier,
2646 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002647 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302648 }
2649
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002650 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002651 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002652 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002653 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002654
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002655 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2656 log.Fields{
2657 "classifier": classifier,
2658 "action": action,
2659 "flowId": logicalFlow.Id,
2660 "intf-id": networkInterfaceID})
2661
David K. Bainbridge794735f2020-02-11 21:01:37 -08002662 classifierProto, err := makeOpenOltClassifierField(classifier)
2663 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002664 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002665 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002666 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002667 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002668 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002669 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002670 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002671 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002672 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2673 OnuId: int32(onuID), // OnuId not required
2674 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002675 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002676 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002677 AllocId: int32(allocID), // AllocId not used
2678 NetworkIntfId: int32(networkInterfaceID),
2679 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002680 Classifier: classifierProto,
2681 Action: actionProto,
2682 Priority: int32(logicalFlow.Priority),
2683 Cookie: logicalFlow.Cookie,
2684 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002685 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002686 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002687 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002688 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002689 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002690}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002691
Esin Karamanae41e2b2019-12-17 18:13:13 +00002692//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2693func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2694 var packetType string
2695 ovid, ivid := false, false
2696 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2697 vid := vlanID & VlanvIDMask
2698 if vid != ReservedVlan {
2699 ovid = true
2700 }
2701 }
2702 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2703 vid := uint32(metadata)
2704 if vid != ReservedVlan {
2705 ivid = true
2706 }
2707 }
2708 if ovid && ivid {
2709 packetType = DoubleTag
2710 } else if !ovid && !ivid {
2711 packetType = Untagged
2712 } else {
2713 packetType = SingleTag
2714 }
2715 return packetType
2716}
2717
2718//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002719func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002720 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002721 action := make(map[string]interface{})
2722 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2723 action[TrapToHost] = true
2724 /* We manage flowId resource pool on per PON port basis.
2725 Since this situation is tricky, as a hack, we pass the NNI port
2726 index (network_intf_id) as PON port Index for the flowId resource
2727 pool. Also, there is no ONU Id available for trapping packets
2728 on NNI port, use onu_id as -1 (invalid)
2729 ****************** CAVEAT *******************
2730 This logic works if the NNI Port Id falls within the same valid
2731 range of PON Port Ids. If this doesn't work for some OLT Vendor
2732 we need to have a re-look at this.
2733 *********************************************
2734 */
2735 onuID := -1
2736 uniID := -1
2737 gemPortID := -1
2738 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002739 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002740 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302741 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002742 "classifier": classifier,
2743 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002744 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002745 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002746 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002747 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002748 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002749 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002750
David K. Bainbridge794735f2020-02-11 21:01:37 -08002751 classifierProto, err := makeOpenOltClassifierField(classifier)
2752 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002753 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002754 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002755 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002756 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002757 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002758 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002759 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002760 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002761 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2762 OnuId: int32(onuID), // OnuId not required
2763 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002764 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002765 FlowType: Downstream,
2766 AllocId: int32(allocID), // AllocId not used
2767 NetworkIntfId: int32(networkInterfaceID),
2768 GemportId: int32(gemPortID), // GemportId not used
2769 Classifier: classifierProto,
2770 Action: actionProto,
2771 Priority: int32(logicalFlow.Priority),
2772 Cookie: logicalFlow.Cookie,
2773 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002774 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002775 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002776 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002777 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002778
David K. Bainbridge794735f2020-02-11 21:01:37 -08002779 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002780}
2781
salmansiddiqui7ac62132019-08-22 03:58:50 +00002782func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2783 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302784 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002785 }
2786 if Dir == tp_pb.Direction_UPSTREAM {
2787 return "upstream", nil
2788 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2789 return "downstream", nil
2790 }
2791 return "", nil
2792}
2793
Kent Hagermane6ff1012020-07-14 15:07:53 -04002794// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302795func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002796 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002797 tpID uint32, uni string) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002798 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002799 intfID := args[IntfID]
2800 onuID := args[OnuID]
2801 uniID := args[UniID]
2802 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002803 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002804 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002805 gemToAes := make(map[uint32]bool)
2806
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002807 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002808 var direction = tp_pb.Direction_UPSTREAM
2809 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002810 case *tp_pb.TechProfileInstance:
Gamze Abaka7650be62021-02-26 10:50:36 +00002811 if IsUpstream(actionInfo[Output].(uint32)) {
2812 attributes = TpInst.UpstreamGemPortAttributeList
2813 } else {
2814 attributes = TpInst.DownstreamGemPortAttributeList
2815 direction = tp_pb.Direction_DOWNSTREAM
2816 }
2817 default:
2818 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
2819 return
2820 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002821
2822 if len(gemPorts) == 1 {
2823 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002824 gemPortID = gemPorts[0]
2825 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002826 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2827 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002828 pBitMap := attributes[idx].PbitMap
2829 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2830 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2831 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
2832 // this pcp bit traffic.
2833 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2834 if pbitSet == pbit1 {
2835 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2836 pbitToGem[pcp] = gemID
2837 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002838 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002839 }
2840 }
2841 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002842 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2843 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2844 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002845 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002846 }
2847
Gamze Abaka7650be62021-02-26 10:50:36 +00002848 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2849 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2850
salmansiddiqui7ac62132019-08-22 03:58:50 +00002851 if ipProto, ok := classifierInfo[IPProto]; ok {
2852 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002853 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002854 "tp-id": tpID,
2855 "alloc-id": allocID,
2856 "intf-id": intfID,
2857 "onu-id": onuID,
2858 "uni-id": uniID,
2859 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002860 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002861 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002862 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002863 }
2864
Girish Gowdra32625212020-04-29 11:26:35 -07002865 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002866 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302867 log.Fields{
2868 "intf-id": intfID,
2869 "onu-id": onuID,
2870 "uni-id": uniID,
2871 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002872 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002873 logger.Warn(ctx, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002874 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002875 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002876 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002877 return
2878 }
2879 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002880 if ethType.(uint32) == EapEthType {
2881 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002882 "intf-id": intfID,
2883 "onu-id": onuID,
2884 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002885 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002886 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002887 var vlanID uint32
2888 if val, ok := classifierInfo[VlanVid]; ok {
2889 vlanID = (val.(uint32)) & VlanvIDMask
2890 } else {
2891 vlanID = DefaultMgmtVlan
2892 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002893 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002894 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002895 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002896 } else if ethType.(uint32) == PPPoEDEthType {
2897 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2898 "tp-id": tpID,
2899 "alloc-id": allocID,
2900 "intf-id": intfID,
2901 "onu-id": onuID,
2902 "uni-id": uniID,
2903 })
2904 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002905 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002906 logger.Warn(ctx, err)
2907 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002908 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002909 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002910 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002911 "intf-id": intfID,
2912 "onu-id": onuID,
2913 "uni-id": uniID,
2914 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002915 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002916 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002917 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002918 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002919 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002920 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002921 "intf-id": intfID,
2922 "onu-id": onuID,
2923 "uni-id": uniID,
2924 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002925 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002926 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002927 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002928 }
2929 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002930 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05302931 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002932 "intf-id": intfID,
2933 "onu-id": onuID,
2934 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05302935 "classifier": classifierInfo,
2936 "action": actionInfo,
2937 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002938 return
2939 }
2940 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002941 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002942 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002943 logger.Warn(ctx, err)
2944 }
2945 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002946}
2947
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002948func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002949 f.gemToFlowIDsKey.RLock()
2950 flowIDList := f.gemToFlowIDs[gemPortID]
2951 f.gemToFlowIDsKey.RUnlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002952 return len(flowIDList) > 1
2953
Gamze Abakafee36392019-10-03 11:17:24 +00002954}
2955
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002956func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpInst *tp_pb.TechProfileInstance, gemPortID uint32) (bool, uint32) {
npujarec5762e2020-01-01 14:08:48 +05302957 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002958 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2959 for _, currentGemPort := range currentGemPorts {
2960 for _, tpGemPort := range tpGemPorts {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002961 if (currentGemPort == tpGemPort.GemportId) && (currentGemPort != gemPortID) {
Gamze Abakafee36392019-10-03 11:17:24 +00002962 return true, currentGemPort
2963 }
2964 }
2965 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00002966 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
2967 return false, 0
2968}
Girish Gowdra54934262019-11-13 14:19:55 +05302969
Gamze Abakacb0e6772021-06-10 08:32:12 +00002970func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002971 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
2972 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
2973 tpInstances := f.techprofile.FindAllTpInstances(ctx, f.deviceHandler.device.Id, sq.tpID, sq.intfID, sq.onuID).([]tp_pb.TechProfileInstance)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002974 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05302975 for i := 0; i < len(tpInstances); i++ {
2976 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00002977 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002978 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Gamze Abakacb0e6772021-06-10 08:32:12 +00002979 logger.Debugw(ctx, "alloc-is-in-use",
2980 log.Fields{
2981 "device-id": f.deviceHandler.device.Id,
2982 "intfID": sq.intfID,
2983 "onuID": sq.onuID,
2984 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002985 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00002986 })
2987 return true
Girish Gowdra54934262019-11-13 14:19:55 +05302988 }
2989 }
2990 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00002991 return false
Gamze Abakafee36392019-10-03 11:17:24 +00002992}
2993
Neha Sharma96b7bf22020-06-15 10:37:32 +00002994func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002995 for _, field := range flows.GetOfbFields(flow) {
2996 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002997 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002998 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002999 } else if field.Type == flows.ETH_DST {
3000 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003001 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003002 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003003 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003004 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003005 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003006 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003007 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003008 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05303009 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003010 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003011 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003012 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003013 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003014 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003015 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003016 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003017 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003018 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003019 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003020 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003021 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003022 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003023 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003024 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003025 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003026 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003027 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003028 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003029 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003030 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003031 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003032 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003033 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003034 return
3035 }
3036 }
3037}
3038
Neha Sharma96b7bf22020-06-15 10:37:32 +00003039func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003040 for _, action := range flows.GetActions(flow) {
3041 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003042 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003043 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003044 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003045 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003046 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003047 }
Scott Baker355d1742019-10-24 10:57:52 -07003048 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003049 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003050 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003051 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003052 if out := action.GetPush(); out != nil {
3053 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003054 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003055 } else {
3056 actionInfo[PushVlan] = true
3057 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003058 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303059 log.Fields{
3060 "push-tpid": actionInfo[TPID].(uint32),
3061 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003062 }
3063 }
Scott Baker355d1742019-10-24 10:57:52 -07003064 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003065 if out := action.GetSetField(); out != nil {
3066 if field := out.GetField(); field != nil {
3067 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003068 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003069 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003070 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3071 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003072 }
3073 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003074 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003075 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003076 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003077 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003078 }
3079 }
3080 return nil
3081}
3082
Neha Sharma96b7bf22020-06-15 10:37:32 +00003083func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003084 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003085 fieldtype := ofbField.GetType()
3086 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003087 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3088 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003089 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003090 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003091 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003092 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003093 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3094 pcp := ofbField.GetVlanPcp()
3095 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003096 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003097 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003098 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003099 }
3100 }
3101}
3102
Neha Sharma96b7bf22020-06-15 10:37:32 +00003103func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003104 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003105 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003106 } else {
3107 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003108 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003109 }
3110}
3111
Neha Sharma96b7bf22020-06-15 10:37:32 +00003112func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003113 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003114 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003115 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3116 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003117 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003118 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003119 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303120 log.Fields{
3121 "newinport": classifierInfo[InPort].(uint32),
3122 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003123 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303124 return olterrors.NewErrNotFound("child-in-port",
3125 log.Fields{
3126 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3127 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003128 }
3129 }
3130 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003131 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003132 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003133 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003134 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003135 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003136 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303137 log.Fields{
3138 "newoutport": actionInfo[Output].(uint32),
3139 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003140 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303141 return olterrors.NewErrNotFound("out-port",
3142 log.Fields{
3143 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3144 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003145 }
3146 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3147 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003148 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003149 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003150 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303151 log.Fields{
3152 "newinport": actionInfo[Output].(uint32),
3153 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003154 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303155 return olterrors.NewErrNotFound("nni-port",
3156 log.Fields{
3157 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3158 "in-port": classifierInfo[InPort].(uint32),
3159 "out-port": actionInfo[Output].(uint32),
3160 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003161 }
3162 }
3163 }
3164 return nil
3165}
Gamze Abakafee36392019-10-03 11:17:24 +00003166
Neha Sharma96b7bf22020-06-15 10:37:32 +00003167func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003168 /* Metadata 8 bytes:
3169 Most Significant 2 Bytes = Inner VLAN
3170 Next 2 Bytes = Tech Profile ID(TPID)
3171 Least Significant 4 Bytes = Port ID
3172 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3173 subscriber related flows.
3174 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003175 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003176 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003177 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003178 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003179 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003180 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003181}
3182
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003183func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3184 for _, sliceElement := range slice {
3185 if sliceElement == item {
3186 return slice
3187 }
3188 }
3189 return append(slice, item)
3190}
3191
3192func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003193 for _, sliceElement := range slice {
3194 if sliceElement == item {
3195 return slice
3196 }
3197 }
3198 return append(slice, item)
3199}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303200
3201// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003202func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303203
3204 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3205 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003206 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003207 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003208 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003209 log.Fields{
3210 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003211 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003212 return uint32(0), err
3213 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003214 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303215 return intfID, nil
3216 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003217 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003218 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003219 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003220 log.Fields{
3221 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003222 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003223 return uint32(0), err
3224 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003225 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303226 return intfID, nil
3227 }
3228 return uint32(0), nil
3229}
3230
3231// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003232func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3233 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3234 if err != nil {
3235 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3236 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3237 return
3238 }
3239 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003240
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003241 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003242 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003243 f.packetInGemPortLock.RUnlock()
3244
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303245 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003246 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003247 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 +05303248 log.Fields{
3249 "pktinkey": pktInkey,
3250 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003251 return
3252 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303253 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003254 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003255 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003256 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003257
npujarec5762e2020-01-01 14:08:48 +05303258 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003259 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 +05303260 log.Fields{
3261 "pktinkey": pktInkey,
3262 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303263}
3264
Esin Karaman7fb80c22020-07-16 14:23:33 +00003265//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3266func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3267 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003268 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003269 return 0, 0, errors.New("invalid packet length")
3270 }
3271 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3272 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3273
3274 var index int8
3275 if outerEthType == 0x8100 {
3276 if innerEthType == 0x8100 {
3277 // q-in-q 802.1ad or 802.1q double tagged packet.
3278 // get the inner vlanId
3279 index = 18
3280 } else {
3281 index = 14
3282 }
3283 priority := (packet[index] >> 5) & 0x7
3284 //13 bits composes vlanId value
3285 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3286 return vlan, priority, nil
3287 }
3288 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3289 return 0, 0, nil
3290}
3291
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003292func (f *OpenOltFlowMgr) loadFlowIDsForGemAndGemIDsForFlow(ctx context.Context) {
3293 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - start")
3294 f.onuGemInfoLock.RLock()
3295 f.gemToFlowIDsKey.Lock()
3296 f.flowIDToGemsLock.Lock()
3297 for _, og := range f.onuGemInfoMap {
3298 for _, gem := range og.GemPorts {
3299 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, f.ponPortIdx, gem)
3300 if err != nil {
3301 f.gemToFlowIDs[gem] = flowIDs
3302 for _, flowID := range flowIDs {
3303 if _, ok := f.flowIDToGems[flowID]; !ok {
3304 f.flowIDToGems[flowID] = []uint32{gem}
3305 } else {
3306 f.flowIDToGems[flowID] = appendUnique32bit(f.flowIDToGems[flowID], gem)
3307 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303308 }
3309 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303310 }
3311 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003312 f.flowIDToGemsLock.Unlock()
3313 f.gemToFlowIDsKey.Unlock()
3314 f.onuGemInfoLock.RUnlock()
3315 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - end")
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303316}
Esin Karamanccb714b2019-11-29 15:02:06 +00003317
Girish Gowdra9602eb42020-09-09 15:50:39 -07003318//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3319// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003320func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003321 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003322 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3323 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003324 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003325 "flow-id": flow.Id,
3326 "device-id": f.deviceHandler.device.Id})
3327 // Remove from device
3328 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3329 // DKB
3330 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3331 log.Fields{
3332 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003333 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003334 return err
3335 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003336
3337 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003338}
3339
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003340func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, ponID uint32, onuID uint32, uniID uint32) *ic.InterAdapterTechProfileDownloadMessage {
3341 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003342 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003343 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
3344 return nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003345 }
3346
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003347 switch tpInst := tpInst.(type) {
3348 case *tp_pb.TechProfileInstance:
3349 logger.Debugw(ctx, "fetched-tp-instance-successfully--formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
3350 return &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID,
3351 TpInstancePath: tpPath,
3352 TechTpInstance: &ic.InterAdapterTechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003353 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003354 case *openoltpb2.EponTechProfileInstance:
3355 return &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID,
3356 TpInstancePath: tpPath,
3357 TechTpInstance: &ic.InterAdapterTechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
3358 }
3359 default:
3360 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003361 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003362 return nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003363}
3364
Girish Gowdrabcf98af2021-07-01 08:24:42 -07003365func (f *OpenOltFlowMgr) getOnuGemInfoList(ctx context.Context) []rsrcMgr.OnuGemInfo {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003366 var onuGemInfoLst []rsrcMgr.OnuGemInfo
3367 f.onuGemInfoLock.RLock()
3368 defer f.onuGemInfoLock.RUnlock()
3369 for _, v := range f.onuGemInfoMap {
3370 onuGemInfoLst = append(onuGemInfoLst, *v)
3371 }
3372 return onuGemInfoLst
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003373}