blob: 8c855a024ae9df7b201f09e05b18ffb492484e5c [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 Gunyel1d20eff2021-07-04 15:39:36 -070030 "github.com/opencord/voltha-lib-go/v5/pkg/meters"
31
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070032 "github.com/opencord/voltha-lib-go/v5/pkg/flows"
33 "github.com/opencord/voltha-lib-go/v5/pkg/log"
34 tp "github.com/opencord/voltha-lib-go/v5/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.
Gamze Abaka3e268512021-09-08 01:14:33 +0000259 onugem, err := rMgr.GetOnuGemInfo(ctx, ponPortIdx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700260 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 Gowdra37f13fa2021-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 Gowdra8a0bdcd2021-05-13 12:31:04 -0700944 f.techprofile = f.resourceMgr.PonRsrMgr.TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400945 tpCount++
Neha Sharma96b7bf22020-06-15 10:37:32 +0000946 logger.Debugw(ctx, "init-tech-profile-done",
Shrey Baid26912972020-04-16 21:02:31 +0530947 log.Fields{
948 "intf-id": intfID,
949 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530950 }
951 }
952 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400953 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530954 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530955 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800956 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530957 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
958 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530959 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000960 logger.Infow(ctx, "populated-techprofile-for-ponports-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530961 log.Fields{
962 "numofTech": tpCount,
963 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
964 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530965 return nil
966}
967
Gamze Abaka7650be62021-02-26 10:50:36 +0000968func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
969 flowContext.classifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000970 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530971 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000972 "uplinkClassifier": flowContext.classifier,
973 "uplinkAction": flowContext.action})
974 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
Manikkaraj k884c1242019-04-11 16:26:42 +0530975 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530976}
977
Gamze Abaka7650be62021-02-26 10:50:36 +0000978func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
979 downlinkClassifier := flowContext.classifier
980 downlinkAction := flowContext.action
981
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700982 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000983 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530984 log.Fields{
985 "downlinkClassifier": downlinkClassifier,
986 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400987 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
988 if vlan, exists := downlinkClassifier[VlanVid]; exists {
989 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700990 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Gamze Abaka7650be62021-02-26 10:50:36 +0000991 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, flowContext.intfID, flowContext.onuID, flowContext.uniID) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000992 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530993 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000994 "flow": flowContext.logicalFlow,
Shrey Baid26912972020-04-16 21:02:31 +0530995 "device-id": f.deviceHandler.device.Id,
Gamze Abaka7650be62021-02-26 10:50:36 +0000996 "onu-id": flowContext.onuID,
997 "intf-id": flowContext.intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800998 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400999 }
1000 }
1001 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301002 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001003
Manikkaraj k884c1242019-04-11 16:26:42 +05301004 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001005 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -04001006 // vlan_vid is a uint32. must be type asserted as such or conversion fails
1007 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +05301008 if ok {
1009 downlinkAction[VlanVid] = dlClVid & 0xfff
1010 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +05301011 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301012 "reason": "failed-to-convert-vlanid-classifier",
1013 "vlan-id": VlanVid,
1014 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +05301015 }
1016
Gamze Abaka7650be62021-02-26 10:50:36 +00001017 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301018}
1019
Gamze Abaka7650be62021-02-26 10:50:36 +00001020func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001021
Gamze Abaka7650be62021-02-26 10:50:36 +00001022 intfID := flowContext.intfID
1023 onuID := flowContext.onuID
1024 uniID := flowContext.uniID
1025 classifier := flowContext.classifier
1026 action := flowContext.action
1027 allocID := flowContext.allocID
1028 gemPortID := flowContext.gemPortID
1029 tpID := flowContext.tpID
1030 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001031 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301032 log.Fields{
1033 "intf-id": intfID,
1034 "onu-id": onuID,
1035 "uni-id": uniID,
1036 "device-id": f.deviceHandler.device.Id,
1037 "classifier": classifier,
1038 "action": action,
1039 "direction": direction,
1040 "alloc-id": allocID,
1041 "gemport-id": gemPortID,
1042 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001043
1044 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001045 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301046 log.Fields{
1047 "device-id": f.deviceHandler.device.Id,
1048 "intf-id": intfID,
1049 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001050 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301051 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001052 classifierProto, err := makeOpenOltClassifierField(classifier)
1053 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301054 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301055 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001056 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301057 log.Fields{
1058 "classifier": *classifierProto,
1059 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001060 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001061 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301062 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301063 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001064 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301065 log.Fields{
1066 "action": *actionProto,
1067 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001068 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301069 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301070 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001071 log.Fields{
1072 "classifier": classifier,
1073 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301074 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001075 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301076 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001077
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001078 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001079 OnuId: int32(onuID),
1080 UniId: int32(uniID),
1081 FlowId: logicalFlow.Id,
1082 FlowType: direction,
1083 AllocId: int32(allocID),
1084 NetworkIntfId: int32(networkIntfID),
1085 GemportId: int32(gemPortID),
1086 Classifier: classifierProto,
1087 Action: actionProto,
1088 Priority: int32(logicalFlow.Priority),
1089 Cookie: logicalFlow.Cookie,
1090 PortNo: flowContext.portNo,
1091 TechProfileId: tpID,
1092 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1093 PbitToGemport: flowContext.pbitToGem,
1094 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001095 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001096 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001097 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301098 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001099 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301100 log.Fields{"direction": direction,
1101 "device-id": f.deviceHandler.device.Id,
1102 "flow": flow,
1103 "intf-id": intfID,
1104 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001105
David K. Bainbridge794735f2020-02-11 21:01:37 -08001106 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301107}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001108
Gamze Abaka7650be62021-02-26 10:50:36 +00001109func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1110
1111 intfID := flowContext.intfID
1112 onuID := flowContext.onuID
1113 uniID := flowContext.uniID
1114 logicalFlow := flowContext.logicalFlow
1115 classifier := flowContext.classifier
1116 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301117
Neha Sharma96b7bf22020-06-15 10:37:32 +00001118 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301119 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301120 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001121 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301122 "action": action,
1123 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001124 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301125 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301126
1127 // Clear the action map
1128 for k := range action {
1129 delete(action, k)
1130 }
1131
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001132 action[TrapToHost] = true
1133 classifier[UDPSrc] = uint32(68)
1134 classifier[UDPDst] = uint32(67)
1135 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301136
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001137 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001138 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301139 log.Fields{
1140 "device-id": f.deviceHandler.device.Id,
1141 "intf-id": intfID,
1142 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001143 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301144 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301145
Neha Sharma96b7bf22020-06-15 10:37:32 +00001146 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301147 log.Fields{
1148 "ul_classifier": classifier,
1149 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001150 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301151 "intf-id": intfID,
1152 "onu-id": onuID,
1153 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301154
David K. Bainbridge794735f2020-02-11 21:01:37 -08001155 classifierProto, err := makeOpenOltClassifierField(classifier)
1156 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301157 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301158 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001159 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001160 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001161 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301162 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301163 }
1164
David K. Bainbridge794735f2020-02-11 21:01:37 -08001165 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001166 OnuId: int32(onuID),
1167 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001168 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001169 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001170 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001171 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001172 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301173 Classifier: classifierProto,
1174 Action: actionProto,
1175 Priority: int32(logicalFlow.Priority),
1176 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001177 PortNo: flowContext.portNo,
1178 TechProfileId: flowContext.tpID,
1179 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1180 PbitToGemport: flowContext.pbitToGem,
1181 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001182 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001183 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001184 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001185 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001186 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301187 log.Fields{
1188 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001189 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301190 "intf-id": intfID,
1191 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301192
David K. Bainbridge794735f2020-02-11 21:01:37 -08001193 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301194}
1195
Esin Karamanae41e2b2019-12-17 18:13:13 +00001196//addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001197func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1198 delete(flowContext.classifier, VlanVid)
1199 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001200}
1201
1202//addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001203func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1204
1205 intfID := flowContext.intfID
1206 onuID := flowContext.onuID
1207 uniID := flowContext.uniID
1208 logicalFlow := flowContext.logicalFlow
1209 classifier := flowContext.classifier
1210 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001211
Neha Sharma96b7bf22020-06-15 10:37:32 +00001212 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001213 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301214 return olterrors.NewErrNotFound("nni-interface-id",
1215 log.Fields{
1216 "classifier": classifier,
1217 "action": action,
1218 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001219 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001220 }
1221
1222 // Clear the action map
1223 for k := range action {
1224 delete(action, k)
1225 }
1226
1227 action[TrapToHost] = true
1228 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001229
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001230 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001231 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001232 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001233 }
1234
Neha Sharma96b7bf22020-06-15 10:37:32 +00001235 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301236 log.Fields{
1237 "ul_classifier": classifier,
1238 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001239 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301240 "device-id": f.deviceHandler.device.Id,
1241 "intf-id": intfID,
1242 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001243
David K. Bainbridge794735f2020-02-11 21:01:37 -08001244 classifierProto, err := makeOpenOltClassifierField(classifier)
1245 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301246 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001247 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001248 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301249 log.Fields{
1250 "classifier": *classifierProto,
1251 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001252 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001253 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301254 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001255 }
1256
David K. Bainbridge794735f2020-02-11 21:01:37 -08001257 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001258 OnuId: int32(onuID),
1259 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001260 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001261 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001262 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001263 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001264 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001265 Classifier: classifierProto,
1266 Action: actionProto,
1267 Priority: int32(logicalFlow.Priority),
1268 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001269 PortNo: flowContext.portNo,
1270 TechProfileId: flowContext.tpID,
1271 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1272 PbitToGemport: flowContext.pbitToGem,
1273 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001274 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001275
David K. Bainbridge794735f2020-02-11 21:01:37 -08001276 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001277 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 -08001278 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001279
David K. Bainbridge794735f2020-02-11 21:01:37 -08001280 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001281}
1282
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001283// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001284func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1285 intfID := flowContext.intfID
1286 onuID := flowContext.onuID
1287 uniID := flowContext.uniID
1288 portNo := flowContext.portNo
1289 allocID := flowContext.allocID
1290 gemPortID := flowContext.gemPortID
1291 logicalFlow := flowContext.logicalFlow
1292 classifier := flowContext.classifier
1293 action := flowContext.action
1294
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001295 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301296 log.Fields{
1297 "intf-id": intfID,
1298 "onu-id": onuID,
1299 "port-no": portNo,
1300 "alloc-id": allocID,
1301 "gemport-id": gemPortID,
1302 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001303 "flow": logicalFlow,
1304 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301305
1306 uplinkClassifier := make(map[string]interface{})
1307 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301308
manikkaraj kbf256be2019-03-25 00:13:48 +05301309 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001310 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001311 uplinkClassifier[PacketTagType] = SingleTag
1312 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001313 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301314 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001315 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001316 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001317 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301318 "device-id": f.deviceHandler.device.Id,
1319 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001320 "intf-id": intfID,
1321 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001322 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301323 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001324 //Add Uplink EthType Flow
1325 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301326 log.Fields{
1327 "ul_classifier": uplinkClassifier,
1328 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001329 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301330 "device-id": f.deviceHandler.device.Id,
1331 "intf-id": intfID,
1332 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301333
David K. Bainbridge794735f2020-02-11 21:01:37 -08001334 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1335 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301336 return olterrors.NewErrInvalidValue(log.Fields{
1337 "classifier": uplinkClassifier,
1338 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301339 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001340 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301341 log.Fields{
1342 "classifier": *classifierProto,
1343 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001344 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001345 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301346 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301347 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001348 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301349 log.Fields{
1350 "action": *actionProto,
1351 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001352 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301353 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301354 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001355 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301356 "action": action,
1357 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001358 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301359 }
1360
David K. Bainbridge794735f2020-02-11 21:01:37 -08001361 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001362 OnuId: int32(onuID),
1363 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001364 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001365 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001366 AllocId: int32(allocID),
1367 NetworkIntfId: int32(networkIntfID),
1368 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301369 Classifier: classifierProto,
1370 Action: actionProto,
1371 Priority: int32(logicalFlow.Priority),
1372 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001373 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001374 TechProfileId: flowContext.tpID,
1375 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1376 PbitToGemport: flowContext.pbitToGem,
1377 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001378 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001379 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001380 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001381 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001382 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301383 log.Fields{
1384 "device-id": f.deviceHandler.device.Id,
1385 "onu-id": onuID,
1386 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001387 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301388 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001389
David K. Bainbridge794735f2020-02-11 21:01:37 -08001390 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301391}
1392
David K. Bainbridge794735f2020-02-11 21:01:37 -08001393func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001394 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001395
1396 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1397 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1398 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001399 if vlanID != ReservedVlan {
1400 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001401 classifier.OVid = vid
1402 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301403 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001404 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1405 vid := uint32(metadata)
1406 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001407 classifier.IVid = vid
1408 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301409 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301410 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001411 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301412 classifier.OPbits = vlanPcp
1413 } else {
1414 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301415 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001416 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1417 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1418 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1419 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001420 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001421 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1422 classifier.PktTagType = pktTagType
1423
1424 switch pktTagType {
1425 case SingleTag:
1426 case DoubleTag:
1427 case Untagged:
1428 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001429 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301430 }
1431 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001432 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301433}
1434
Gamze Abaka724d0852020-03-18 12:10:24 +00001435func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001436 var actionCmd openoltpb2.ActionCmd
1437 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301438 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001439 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301440 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001441 if _, ok := actionInfo[VlanPcp]; ok {
1442 action.Cmd.RemarkInnerPbits = true
1443 action.IPbits = actionInfo[VlanPcp].(uint32)
1444 if _, ok := actionInfo[VlanVid]; ok {
1445 action.Cmd.TranslateInnerTag = true
1446 action.IVid = actionInfo[VlanVid].(uint32)
1447 }
1448 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001449 } else if _, ok := actionInfo[PushVlan]; ok {
1450 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301451 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001452 if _, ok := actionInfo[VlanPcp]; ok {
1453 action.OPbits = actionInfo[VlanPcp].(uint32)
1454 action.Cmd.RemarkOuterPbits = true
1455 if _, ok := classifierInfo[VlanVid]; ok {
1456 action.IVid = classifierInfo[VlanVid].(uint32)
1457 action.Cmd.TranslateInnerTag = true
1458 }
1459 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001460 } else if _, ok := actionInfo[TrapToHost]; ok {
1461 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301462 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001463 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301464 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001465 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301466}
1467
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001468// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001469func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001470 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301471}
1472
Gamze Abakafee36392019-10-03 11:17:24 +00001473// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdra37f13fa2021-08-16 10:59:45 -07001474// We also force release scheduler and queues associated with the tp instance. Theoretically there could be
1475// an issue if the upstream scheduler (DBA) is shared across multiple UNI and we force release it, given that
1476// this function is only meant to clean up TP instances of a given UNI. But in practicality this routine
1477// is only meant to be called when the clean up of resource for the whole ONU is taking place.
1478// The reason for introducing the force cleanup of scheduler and queues (on the OLT) was introduced here
1479// because it was observed that if the ONU device was deleted too soon after the flows were
1480// unprovisioned on that ONU, the scheduler and queue removal pertinent to that ONU would remain
1481// uncleaned on the OLT. So we force clean up here and ignore any error that OLT returns during the
1482// force cleanup (possible if the OLT has already cleared those resources).
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001483func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301484 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001485 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1486
Gamze Abakafee36392019-10-03 11:17:24 +00001487 for _, tpID := range tpIDList {
Girish Gowdra37f13fa2021-08-16 10:59:45 -07001488
1489 // Force cleanup scheduler/queues -- start
1490 uniPortNum := MkUniPortNum(ctx, intfID, onuID, uniID)
1491 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1492 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
1493 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1494 if err != nil || tpInst == nil { // This should not happen, something wrong in KV backend transaction
1495 logger.Warnw(ctx, "tech-profile-not-in-kv-store",
1496 log.Fields{
1497 "tp-id": tpID,
1498 "path": tpPath})
1499 }
1500 switch tpInstance := tpInst.(type) {
1501 case *tp_pb.TechProfileInstance:
1502 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1503 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1504 }
1505 // Force cleanup scheduler/queues -- end
1506
1507 // Now remove the tp instance
npujarec5762e2020-01-01 14:08:48 +05301508 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001509 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301510 // return err
1511 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001512 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001513 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 +00001514 }
1515 return nil
1516}
1517
1518// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301519func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001520 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001521 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001522 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001523 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301524 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1525 log.Fields{
1526 "tp-id": tpID,
1527 "uni-port-name": uniPortName,
1528 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001529 }
1530 return nil
1531}
1532
David K. Bainbridge794735f2020-02-11 21:01:37 -08001533func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001534
1535 var intfID uint32
1536 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1537 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1538 */
1539 if deviceFlow.AccessIntfId != -1 {
1540 intfID = uint32(deviceFlow.AccessIntfId)
1541 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001542 // We need to log the valid interface ID.
1543 // 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 +00001544 intfID = uint32(deviceFlow.NetworkIntfId)
1545 }
1546
Neha Sharma96b7bf22020-06-15 10:37:32 +00001547 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301548 "flow": *deviceFlow,
1549 "device-id": f.deviceHandler.device.Id,
1550 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001551 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001552
1553 st, _ := status.FromError(err)
1554 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001555 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001556 "err": err,
1557 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301558 "device-id": f.deviceHandler.device.Id,
1559 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001560 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301561 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001562
1563 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001564 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301565 log.Fields{"err": err,
1566 "device-flow": deviceFlow,
1567 "device-id": f.deviceHandler.device.Id,
1568 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001569 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001570 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001571 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301572 log.Fields{
1573 "flow": *deviceFlow,
1574 "device-id": f.deviceHandler.device.Id,
1575 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001576
1577 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1578 if deviceFlow.AccessIntfId != -1 {
1579 // No need to register the flow if it is a trap on nni flow.
1580 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1581 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1582 return err
1583 }
1584 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001585 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001586}
1587
Neha Sharma96b7bf22020-06-15 10:37:32 +00001588func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1589 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301590 log.Fields{
1591 "flow": *deviceFlow,
1592 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001593 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001594 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001595 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001596 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301597 log.Fields{
1598 "err": err,
1599 "deviceFlow": deviceFlow,
1600 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001601 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001602 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001603 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001604 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001605
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001606 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001607 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001608 "of-flow-id": ofFlowID,
1609 "flow": *deviceFlow,
1610 "device-id": f.deviceHandler.device.Id,
1611 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001612 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301613}
1614
David K. Bainbridge794735f2020-02-11 21:01:37 -08001615func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001616
1617 classifierInfo := make(map[string]interface{})
1618 actionInfo := make(map[string]interface{})
1619
1620 classifierInfo[EthType] = uint32(LldpEthType)
1621 classifierInfo[PacketTagType] = Untagged
1622 actionInfo[TrapToHost] = true
1623
1624 // LLDP flow is installed to trap LLDP packets on the NNI port.
1625 // We manage flow_id resource pool on per PON port basis.
1626 // Since this situation is tricky, as a hack, we pass the NNI port
1627 // index (network_intf_id) as PON port Index for the flow_id resource
1628 // pool. Also, there is no ONU Id available for trapping LLDP packets
1629 // on NNI port, use onu_id as -1 (invalid)
1630 // ****************** CAVEAT *******************
1631 // This logic works if the NNI Port Id falls within the same valid
1632 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1633 // we need to have a re-look at this.
1634 // *********************************************
1635
1636 var onuID = -1
1637 var uniID = -1
1638 var gemPortID = -1
1639
Neha Sharma96b7bf22020-06-15 10:37:32 +00001640 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001641 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301642 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001643 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001644 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001645 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001646 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001647 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001648
David K. Bainbridge794735f2020-02-11 21:01:37 -08001649 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1650 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301651 return olterrors.NewErrInvalidValue(
1652 log.Fields{
1653 "classifier": classifierInfo,
1654 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001655 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001656 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301657 log.Fields{
1658 "classifier": *classifierProto,
1659 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001660 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001661 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301662 return olterrors.NewErrInvalidValue(
1663 log.Fields{
1664 "action": actionInfo,
1665 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001666 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001667 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301668 log.Fields{
1669 "action": *actionProto,
1670 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001671
1672 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1673 OnuId: int32(onuID), // OnuId not required
1674 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001675 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001676 FlowType: Downstream,
1677 NetworkIntfId: int32(networkInterfaceID),
1678 GemportId: int32(gemPortID),
1679 Classifier: classifierProto,
1680 Action: actionProto,
1681 Priority: int32(flow.Priority),
1682 Cookie: flow.Cookie,
1683 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001684 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001685 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301686 log.Fields{
1687 "flow": downstreamflow,
1688 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001689 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001690 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301691 log.Fields{
1692 "device-id": f.deviceHandler.device.Id,
1693 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001694 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001695
David K. Bainbridge794735f2020-02-11 21:01:37 -08001696 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301697}
1698
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001699func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1700 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001701}
1702
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001703//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001704func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001705 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1706 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1707 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001708 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301709 log.Fields{
1710 "intf-id": intfID,
1711 "onu-id": onuID,
1712 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001713 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001714 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301715 return nil, olterrors.NewErrNotFound("onu-child-device",
1716 log.Fields{
1717 "onu-id": onuID,
1718 "intf-id": intfID,
1719 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001720 }
1721 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1722 //better to ad the device to cache here.
1723 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1724 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001725 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301726 log.Fields{
1727 "intf-id": intfID,
1728 "onu-id": onuID,
1729 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001730 }
1731
1732 return onuDev.(*OnuDevice), nil
1733}
1734
1735//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001736func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1737 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301738 log.Fields{
1739 "pon-port": intfID,
1740 "onu-id": onuID,
1741 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001742 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001743 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001744 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301745 return nil, olterrors.NewErrNotFound("onu",
1746 log.Fields{
1747 "interface-id": parentPortNo,
1748 "onu-id": onuID,
1749 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001750 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301751 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001752 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301753 log.Fields{
1754 "device-id": f.deviceHandler.device.Id,
1755 "child_device_id": onuDevice.Id,
1756 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301757 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301758}
1759
Neha Sharma96b7bf22020-06-15 10:37:32 +00001760func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1761 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301762 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001763 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301764 log.Fields{
1765 "intf-id": intfID,
1766 "onu-id": onuID,
1767 "uni-id": uniID,
1768 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001769 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301770 }
1771
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001772 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpInstancePath: tpPath, GemPortId: gemPortID}
1773 logger.Infow(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301774 log.Fields{
1775 "msg": *delGemPortMsg,
1776 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001777 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301778 delGemPortMsg,
1779 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001780 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001781 onuDev.deviceType,
1782 onuDev.deviceID,
1783 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301784 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1785 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001786 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301787 "to-adapter": onuDev.deviceType,
1788 "onu-id": onuDev.deviceID,
1789 "proxyDeviceID": onuDev.proxyDeviceID,
1790 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301791 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001792 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301793 log.Fields{
1794 "msg": delGemPortMsg,
1795 "from-adapter": f.deviceHandler.device.Type,
1796 "to-adapter": onuDev.deviceType,
1797 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301798 return nil
1799}
1800
Neha Sharma96b7bf22020-06-15 10:37:32 +00001801func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1802 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301803 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001804 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301805 log.Fields{
1806 "intf-id": intfID,
1807 "onu-id": onuID,
1808 "uni-id": uniID,
1809 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001810 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301811 }
1812
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001813 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpInstancePath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001814 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301815 log.Fields{
1816 "msg": *delTcontMsg,
1817 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001818 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301819 delTcontMsg,
1820 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001821 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001822 onuDev.deviceType,
1823 onuDev.deviceID,
1824 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301825 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1826 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001827 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301828 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1829 "proxyDeviceID": onuDev.proxyDeviceID,
1830 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301831 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001832 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301833 log.Fields{
1834 "msg": delTcontMsg,
1835 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301836 return nil
1837}
1838
Girish Gowdrac3037402020-01-22 20:29:53 +05301839// Once the gemport is released for a given onu, it also has to be cleared from local cache
1840// which was used for deriving the gemport->logicalPortNo during packet-in.
1841// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1842// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001843func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001844 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301845 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001846 "gem-port-id": gemPortID,
1847 "intf-id": intfID,
1848 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001849 "device-id": f.deviceHandler.device.Id})
1850 f.onuGemInfoLock.RLock()
1851 onugem, ok := f.onuGemInfoMap[onuID]
1852 f.onuGemInfoLock.RUnlock()
1853 if !ok {
1854 logger.Warnw(ctx, "onu gem info already cleared from cache", log.Fields{
1855 "gem-port-id": gemPortID,
1856 "intf-id": intfID,
1857 "onu-id": onuID,
1858 "device-id": f.deviceHandler.device.Id})
1859 return
1860 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001861deleteLoop:
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001862 for j, gem := range onugem.GemPorts {
1863 // If the gemport is found, delete it from local cache.
1864 if gem == gemPortID {
1865 onugem.GemPorts = append(onugem.GemPorts[:j], onugem.GemPorts[j+1:]...)
1866 f.onuGemInfoLock.Lock()
1867 f.onuGemInfoMap[onuID] = onugem
1868 f.onuGemInfoLock.Unlock()
1869 logger.Infow(ctx, "removed-gemport-from-local-cache",
1870 log.Fields{
1871 "intf-id": intfID,
1872 "onu-id": onuID,
1873 "deletedgemport-id": gemPortID,
1874 "gemports": onugem.GemPorts,
1875 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001876 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301877 }
1878 }
1879}
1880
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301881//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001882// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001883func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Girish Gowdra82c80982021-03-26 16:22:02 -07001884 gemPortID int32, flowID uint64, portNum uint32, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001885
Girish Gowdraa482f272021-03-24 23:04:19 -07001886 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
1887 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001888 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1889 log.Fields{
1890 "tpPath": tpPath,
1891 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001892
1893 used := f.isGemPortUsedByAnotherFlow(uint32(gemPortID))
1894
1895 if used {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001896 f.gemToFlowIDsKey.RLock()
1897 flowIDs := f.gemToFlowIDs[uint32(gemPortID)]
1898 f.gemToFlowIDsKey.RUnlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001899
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001900 for i, flowIDinMap := range flowIDs {
1901 if flowIDinMap == flowID {
1902 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001903 f.gemToFlowIDsKey.Lock()
1904 f.gemToFlowIDs[uint32(gemPortID)] = flowIDs
1905 f.gemToFlowIDsKey.Unlock()
1906 // everytime gemToFlowIDs cache is updated the same should be updated
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001907 // in kv store by calling UpdateFlowIDsForGem
Girish Gowdraa482f272021-03-24 23:04:19 -07001908 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, intfID, uint32(gemPortID), flowIDs); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001909 return err
1910 }
1911 break
1912 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001913 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001914 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1915 log.Fields{
1916 "gemport-id": gemPortID,
1917 "usedByFlows": flowIDs,
1918 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -07001919
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001920 return nil
1921 }
1922 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 -07001923 f.deleteGemPortFromLocalCache(ctx, intfID, uint32(onuID), uint32(gemPortID))
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001924 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, intfID, uint32(onuID), uint32(gemPortID)) // ignore error and proceed.
1925 //everytime an entry is deleted from gemToFlowIDs cache, the same should be updated in kv as well
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001926 // by calling DeleteFlowIDsForGem
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001927 f.gemToFlowIDsKey.Lock()
1928 delete(f.gemToFlowIDs, uint32(gemPortID))
1929 f.gemToFlowIDsKey.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001930
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001931 f.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, uint32(gemPortID))
1932
1933 f.resourceMgr.FreeGemPortID(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001934
Mahir Gunyel1d20eff2021-07-04 15:39:36 -07001935 //First remove TCONT from child if needed. Then remove the GEM.
1936 //It is expected from child to clean ani side conf if all GEMs of TP are deleted.
1937 //Before this, ensure that the related TCONT deletions are informed to child.
1938 //Refer to VOL-4215.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001939 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1940 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1941 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1942 log.Fields{
1943 "tp-id": tpID,
1944 "path": tpPath}, err)
1945 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001946 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001947 case *tp_pb.TechProfileInstance:
Gamze Abakacb0e6772021-06-10 08:32:12 +00001948 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst, uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001949 if !ok {
Girish Gowdraa482f272021-03-24 23:04:19 -07001950 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001951 logger.Warn(ctx, err)
1952 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001953 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001954 logger.Warn(ctx, err)
1955 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001956 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 -07001957 logger.Warn(ctx, err)
1958 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001959 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 -07001960 logger.Warn(ctx, err)
1961 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001962 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001963 case *tp_pb.EponTechProfileInstance:
Girish Gowdraa482f272021-03-24 23:04:19 -07001964 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001965 logger.Warn(ctx, err)
1966 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001967 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001968 logger.Warn(ctx, err)
1969 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001970 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001971 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001972 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001973 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05301974 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07001975 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05301976 "onu-id": onuID,
1977 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001978 "device-id": f.deviceHandler.device.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001979 "alloc-id": techprofileInst.AllocId})
Gamze Abakafee36392019-10-03 11:17:24 +00001980 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001981 default:
1982 logger.Errorw(ctx, "error-unknown-tech",
1983 log.Fields{
1984 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001985 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001986
Mahir Gunyel1d20eff2021-07-04 15:39:36 -07001987 // Delete the gem port on the ONU. Send Gem Removal After TCONT removal.
1988 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
1989 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
1990 log.Fields{
1991 "err": err,
1992 "intfID": intfID,
1993 "onu-id": onuID,
1994 "uni-id": uniID,
1995 "device-id": f.deviceHandler.device.Id,
1996 "gemport-id": gemPortID})
1997 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301998 return nil
1999}
2000
David K. Bainbridge794735f2020-02-11 21:01:37 -08002001// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002002func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002003 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302004 log.Fields{
2005 "flowDirection": flowDirection,
2006 "flow": *flow,
2007 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002008
2009 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002010 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002011 }
2012
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302013 classifierInfo := make(map[string]interface{})
2014
Neha Sharma96b7bf22020-06-15 10:37:32 +00002015 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302016 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002017 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002018 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302019 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302020
David K. Bainbridge794735f2020-02-11 21:01:37 -08002021 onuID := int32(onu)
2022 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002023 tpID, err := getTpIDFromFlow(ctx, flow)
2024 if err != nil {
2025 return olterrors.NewErrNotFound("tp-id",
2026 log.Fields{
2027 "flow": flow,
2028 "intf-id": Intf,
2029 "onu-id": onuID,
2030 "uni-id": uniID,
2031 "device-id": f.deviceHandler.device.Id}, err)
2032 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302033
2034 for _, field := range flows.GetOfbFields(flow) {
2035 if field.Type == flows.IP_PROTO {
2036 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002037 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302038 }
2039 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002040 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302041 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002042 "flow-id": flow.Id,
2043 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302044 "onu-id": onuID,
2045 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302046
2047 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2048 onuID = -1
2049 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002050 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
2051 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002052 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002053 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002054 log.Fields{
2055 "port-number": inPort,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002056 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002057 return err
David K. Bainbridge794735f2020-02-11 21:01:37 -08002058 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302059 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002060
2061 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
2062 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002063 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2064 return err
2065 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002066
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002067 f.flowIDToGemsLock.Lock()
2068 gems, ok := f.flowIDToGems[flow.Id]
2069 if !ok {
2070 logger.Errorw(ctx, "flow-id-to-gem-map-not-found", log.Fields{"flowID": flow.Id})
2071 f.flowIDToGemsLock.Unlock()
2072 return olterrors.NewErrNotFound("flow-id-to-gem-map-not-found", log.Fields{"flowID": flow.Id}, nil)
2073 }
2074 copyOfGems := make([]uint32, len(gems))
2075 _ = copy(copyOfGems, gems)
2076 // Delete the flow-id to gemport list entry from the map now the flow is deleted.
2077 delete(f.flowIDToGems, flow.Id)
2078 f.flowIDToGemsLock.Unlock()
2079
2080 logger.Debugw(ctx, "gems-to-be-cleared", log.Fields{"gems": copyOfGems})
2081 for _, gem := range copyOfGems {
2082 if err = f.clearResources(ctx, Intf, onuID, uniID, int32(gem), flow.Id, portNum, tpID); err != nil {
Girish Gowdra0aca4982021-01-04 12:44:27 -08002083 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002084 "flow-id": flow.Id,
2085 "device-id": f.deviceHandler.device.Id,
2086 "onu-id": onuID,
2087 "intf": Intf,
2088 "gem": gem,
2089 "err": err,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002090 })
2091 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302092 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302093 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002094
Girish Gowdra82c80982021-03-26 16:22:02 -07002095 // Decrement reference count for the meter associated with the given <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
2096 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, Intf, uint32(onuID), uint32(uniID), tpID, false); err != nil {
2097 return err
2098 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002099 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002100}
2101
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002102//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002103func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002104
Matteo Scandolof16389e2021-05-18 00:47:08 +00002105 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302106 var direction string
2107 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002108
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302109 for _, action := range flows.GetActions(flow) {
2110 if action.Type == flows.OUTPUT {
2111 if out := action.GetOutput(); out != nil {
2112 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002113 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302114 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002115 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002116 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002117 }
2118 }
2119 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002120
2121 if flows.HasGroup(flow) {
2122 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002123 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Esin Karamanccb714b2019-11-29 15:02:06 +00002124 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302125 direction = Upstream
2126 } else {
2127 direction = Downstream
2128 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302129
Girish Gowdracefae192020-03-19 18:14:10 -07002130 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002131 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002132
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002133 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002134}
2135
Esin Karamanae41e2b2019-12-17 18:13:13 +00002136//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2137func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2138 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2139 if ethType, ok := classifierInfo[EthType]; ok {
2140 if ethType.(uint32) == IPv4EthType {
2141 if ipProto, ok := classifierInfo[IPProto]; ok {
2142 if ipProto.(uint32) == IgmpProto {
2143 return true
2144 }
2145 }
2146 }
2147 }
2148 }
2149 return false
2150}
2151
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002152// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
2153func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *voltha.OfpFlowStats, addFlow bool, flowMetadata *voltha.FlowMetadata) error {
2154 // Step1 : Fill flowControlBlock
2155 // Step2 : Push the flowControlBlock to ONU channel
2156 // Step3 : Wait on response channel for response
2157 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002158 startTime := time.Now()
2159 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002160 errChan := make(chan error)
2161 flowCb := flowControlBlock{
2162 ctx: ctx,
2163 addFlow: addFlow,
2164 flow: flow,
2165 flowMetadata: flowMetadata,
2166 errChan: &errChan,
2167 }
2168 inPort, outPort := getPorts(flow)
2169 var onuID uint32
2170 if inPort != InvalidPort && outPort != InvalidPort {
2171 _, _, onuID, _ = ExtractAccessFromFlow(inPort, outPort)
2172 }
2173 // inPort or outPort is InvalidPort for trap-from-nni flows.
2174 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2175 // Send the flowCb on the ONU flow channel
2176 f.incomingFlows[onuID] <- flowCb
2177 // Wait on the channel for flow handlers return value
2178 err := <-errChan
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002179 logger.Infow(ctx, "process-flow--received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002180 return err
2181}
2182
2183// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2184// Each incoming flow is processed in a synchronous manner, i.e., the flow is processed to completion before picking another
2185func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(subscriberFlowChannel chan flowControlBlock) {
2186 for {
2187 // block on the channel to receive an incoming flow
2188 // process the flow completely before proceeding to handle the next flow
2189 flowCb := <-subscriberFlowChannel
2190 if flowCb.addFlow {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002191 logger.Info(flowCb.ctx, "adding-flow-start")
2192 startTime := time.Now()
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002193 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002194 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002195 // Pass the return value over the return channel
2196 *flowCb.errChan <- err
2197 } else {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002198 logger.Info(flowCb.ctx, "removing-flow-start")
2199 startTime := time.Now()
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002200 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002201 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002202 // Pass the return value over the return channel
2203 *flowCb.errChan <- err
2204 }
2205 }
2206}
2207
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002208// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302209// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002210func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002211 classifierInfo := make(map[string]interface{})
2212 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002213 var UsMeterID uint32
2214 var DsMeterID uint32
2215
Neha Sharma96b7bf22020-06-15 10:37:32 +00002216 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302217 log.Fields{
2218 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002219 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002220 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002221
Neha Sharma96b7bf22020-06-15 10:37:32 +00002222 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002223 if err != nil {
2224 // Error logging is already done in the called function
2225 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002226 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302227 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002228
Esin Karamanccb714b2019-11-29 15:02:06 +00002229 if flows.HasGroup(flow) {
2230 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002231 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002232 }
2233
manikkaraj k17652a72019-05-06 09:06:36 -04002234 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002235 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002236 if err != nil {
2237 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002238 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002239 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002240
Neha Sharma96b7bf22020-06-15 10:37:32 +00002241 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302242 log.Fields{
2243 "classifierinfo_inport": classifierInfo[InPort],
2244 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002245 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002246
Humera Kouser94d7a842019-08-25 19:04:32 -04002247 if ethType, ok := classifierInfo[EthType]; ok {
2248 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002249 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002250 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002251 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002252 if ethType.(uint32) == PPPoEDEthType {
2253 if voltha.Port_ETHERNET_NNI == IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
2254 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2255 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2256 }
2257 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002258 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002259 if ipProto, ok := classifierInfo[IPProto]; ok {
2260 if ipProto.(uint32) == IPProtoDhcp {
2261 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302262 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002263 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002264 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002265 }
2266 }
2267 }
2268 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002269 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002270 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002271 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002272 }
A R Karthick1f85b802019-10-11 05:06:05 +00002273
npujarec5762e2020-01-01 14:08:48 +05302274 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002275 // also update flowmgr cache
2276 f.onuGemInfoLock.Lock()
2277 onugem, ok := f.onuGemInfoMap[onuID]
2278 if ok {
2279 found := false
2280 for _, uni := range onugem.UniPorts {
2281 if uni == portNo {
2282 found = true
2283 break
2284 }
2285 }
2286 if !found {
2287 onugem.UniPorts = append(onugem.UniPorts, portNo)
2288 f.onuGemInfoMap[onuID] = onugem
2289 logger.Infow(ctx, "added uni port to onugem cache", log.Fields{"uni": portNo})
2290 }
2291 }
2292 f.onuGemInfoLock.Unlock()
A R Karthick1f85b802019-10-11 05:06:05 +00002293
Neha Sharma96b7bf22020-06-15 10:37:32 +00002294 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002295 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302296 return olterrors.NewErrNotFound("tpid-for-flow",
2297 log.Fields{
2298 "flow": flow,
2299 "intf-id": IntfID,
2300 "onu-id": onuID,
2301 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002302 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002303 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302304 log.Fields{
2305 "tp-id": TpID,
2306 "intf-id": intfID,
2307 "onu-id": onuID,
2308 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002309 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002310 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002311 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002312 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002313 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002314 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002315
2316 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002317 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002318}
Girish Gowdra3d633032019-12-10 16:37:05 +05302319
Esin Karamanccb714b2019-11-29 15:02:06 +00002320// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002321func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002322 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002323 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302324 "classifier-info": classifierInfo,
2325 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002326
Esin Karaman65409d82020-03-18 10:58:18 +00002327 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002328 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002329 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002330 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002331
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002332 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002333
David K. Bainbridge794735f2020-02-11 21:01:37 -08002334 onuID := NoneOnuID
2335 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002336
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002337 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002338 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002339 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002340 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002341 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2342 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002343 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002344 }
2345 groupID := actionInfo[GroupID].(uint32)
2346 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002347 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002348 FlowType: Multicast,
2349 NetworkIntfId: int32(networkInterfaceID),
2350 GroupId: groupID,
2351 Classifier: classifierProto,
2352 Priority: int32(flow.Priority),
2353 Cookie: flow.Cookie}
2354
Kent Hagermane6ff1012020-07-14 15:07:53 -04002355 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002356 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002357 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002358 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002359 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002360 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002361 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002362 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002363 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002364 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002365 //cached group can be removed now
2366 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002367 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002368 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002369 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002370
David K. Bainbridge794735f2020-02-11 21:01:37 -08002371 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002372}
2373
Esin Karaman65409d82020-03-18 10:58:18 +00002374//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2375func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2376 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002377 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002378 if err != nil {
2379 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2380 }
2381 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002382 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002383
2384 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2385 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002386}
2387
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002388//sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002389func (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 -07002390
Neha Sharma96b7bf22020-06-15 10:37:32 +00002391 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302392 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002393 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302394 log.Fields{
2395 "intf-id": intfID,
2396 "onu-id": onuID,
2397 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002398 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302399 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002400 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002401
Neha Sharma96b7bf22020-06-15 10:37:32 +00002402 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002403 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{
2404 UniId: uniID,
2405 TpInstancePath: tpPath,
2406 TechTpInstance: &ic.InterAdapterTechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
2407 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002408 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002409 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
manikkaraj k17652a72019-05-06 09:06:36 -04002410 tpDownloadMsg,
2411 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03002412 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002413 onuDev.deviceType,
2414 onuDev.deviceID,
2415 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002416 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302417 return olterrors.NewErrCommunication("send-techprofile-download-request",
2418 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03002419 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05302420 "to-adapter": onuDev.deviceType,
2421 "onu-id": onuDev.deviceID,
2422 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002423 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002424 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302425 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302426}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002427
Girish Gowdra37f13fa2021-08-16 10:59:45 -07002428//AddOnuInfoToFlowMgrCacheAndKvStore function adds onu info to cache and kvstore
2429func (f *OpenOltFlowMgr) AddOnuInfoToFlowMgrCacheAndKvStore(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302430
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002431 f.onuGemInfoLock.RLock()
2432 _, ok := f.onuGemInfoMap[onuID]
2433 f.onuGemInfoLock.RUnlock()
Girish Gowdra9602eb42020-09-09 15:50:39 -07002434 // If the ONU already exists in onuGemInfo list, nothing to do
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002435 if ok {
2436 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2437 log.Fields{"onuID": onuID,
2438 "serialNum": serialNum})
2439 return nil
Girish Gowdra9602eb42020-09-09 15:50:39 -07002440 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002441
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002442 onuGemInfo := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2443 f.onuGemInfoLock.Lock()
2444 f.onuGemInfoMap[onuID] = &onuGemInfo
2445 f.onuGemInfoLock.Unlock()
2446 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onuID, onuGemInfo); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002447 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302448 }
Girish Gowdra37f13fa2021-08-16 10:59:45 -07002449 logger.Infow(ctx, "added-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302450 log.Fields{
2451 "intf-id": intfID,
2452 "onu-id": onuID,
2453 "serial-num": serialNum,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002454 "onu": onuGemInfo,
Shrey Baid26912972020-04-16 21:02:31 +05302455 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002456 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002457}
2458
Girish Gowdra37f13fa2021-08-16 10:59:45 -07002459//RemoveOnuInfoFromFlowMgrCacheAndKvStore function adds onu info to cache and kvstore
2460func (f *OpenOltFlowMgr) RemoveOnuInfoFromFlowMgrCacheAndKvStore(ctx context.Context, intfID uint32, onuID uint32) error {
2461
2462 f.onuGemInfoLock.Lock()
2463 delete(f.onuGemInfoMap, onuID)
2464 f.onuGemInfoLock.Unlock()
2465
2466 if err := f.resourceMgr.DelOnuGemInfo(ctx, intfID, onuID); err != nil {
2467 return err
2468 }
2469 logger.Infow(ctx, "deleted-onuinfo",
2470 log.Fields{
2471 "intf-id": intfID,
2472 "onu-id": onuID,
2473 "device-id": f.deviceHandler.device.Id})
2474 return nil
2475}
2476
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302477//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302478func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002479
Neha Sharma96b7bf22020-06-15 10:37:32 +00002480 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302481 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002482 "gem-port-id": gemPort,
2483 "intf-id": intfID,
2484 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002485 "device-id": f.deviceHandler.device.Id})
2486 f.onuGemInfoLock.RLock()
2487 onugem, ok := f.onuGemInfoMap[onuID]
2488 f.onuGemInfoLock.RUnlock()
2489 if !ok {
2490 logger.Warnw(ctx, "onu gem info is missing", log.Fields{
2491 "gem-port-id": gemPort,
2492 "intf-id": intfID,
2493 "onu-id": onuID,
2494 "device-id": f.deviceHandler.device.Id})
2495 return
2496 }
2497
2498 if onugem.OnuID == onuID {
2499 // check if gem already exists , else update the cache and kvstore
2500 for _, gem := range onugem.GemPorts {
2501 if gem == gemPort {
2502 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
2503 log.Fields{
2504 "gem": gemPort,
2505 "device-id": f.deviceHandler.device.Id})
2506 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302507 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302508 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002509 onugem.GemPorts = append(onugem.GemPorts, gemPort)
2510 f.onuGemInfoLock.Lock()
2511 f.onuGemInfoMap[onuID] = onugem
2512 f.onuGemInfoLock.Unlock()
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002513 logger.Debugw(ctx, "updated onu gem info from cache", log.Fields{"onugem": onugem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002514 } else {
2515 logger.Warnw(ctx, "mismatched onu id", log.Fields{
2516 "gem-port-id": gemPort,
2517 "intf-id": intfID,
2518 "onu-id": onuID,
2519 "device-id": f.deviceHandler.device.Id})
2520 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302521 }
npujarec5762e2020-01-01 14:08:48 +05302522 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302523 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002524 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302525 log.Fields{
2526 "intf-id": intfID,
2527 "onu-id": onuID,
2528 "gemPort": gemPort,
2529 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002530 return
2531 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002532 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302533 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002534 "gem-port-id": gemPort,
2535 "intf-id": intfID,
2536 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002537 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002538}
2539
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002540//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302541func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002542 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002543
2544 if packetIn.IntfType == "pon" {
2545 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002546 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002547 onuID, uniID := packetIn.OnuId, packetIn.UniId
2548 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 +00002549
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002550 if packetIn.PortNo != 0 {
2551 logicalPortNum = packetIn.PortNo
2552 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002553 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002554 }
2555 // 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 +00002556 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002557 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002558 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002559 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002560
2561 if logger.V(log.DebugLevel) {
2562 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2563 log.Fields{
2564 "logical-port-num": logicalPortNum,
2565 "intf-type": packetIn.IntfType,
2566 "packet": hex.EncodeToString(packetIn.Pkt),
2567 })
2568 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002569 return logicalPortNum, nil
2570}
2571
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002572//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002573func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002574 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002575
2576 ctag, priority, err := getCTagFromPacket(ctx, packet)
2577 if err != nil {
2578 return 0, err
2579 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302580
Esin Karaman7fb80c22020-07-16 14:23:33 +00002581 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002582 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002583 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002584 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002585 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302586 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002587 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302588 log.Fields{
2589 "pktinkey": pktInkey,
2590 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002591
2592 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002593 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302594 //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 +00002595 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302596 if err == nil {
2597 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002598 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302599 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002600 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002601 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302602 log.Fields{
2603 "pktinkey": pktInkey,
2604 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302605 return gemPortID, nil
2606 }
2607 }
Shrey Baid26912972020-04-16 21:02:31 +05302608 return uint32(0), olterrors.NewErrNotFound("gem-port",
2609 log.Fields{
2610 "pktinkey": pktInkey,
2611 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002612
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002613}
2614
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002615func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2616 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002617 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002618 classifier[PacketTagType] = DoubleTag
2619 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002620 /* We manage flowId resource pool on per PON port basis.
2621 Since this situation is tricky, as a hack, we pass the NNI port
2622 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002623 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002624 on NNI port, use onu_id as -1 (invalid)
2625 ****************** CAVEAT *******************
2626 This logic works if the NNI Port Id falls within the same valid
2627 range of PON Port Ids. If this doesn't work for some OLT Vendor
2628 we need to have a re-look at this.
2629 *********************************************
2630 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002631 onuID := -1
2632 uniID := -1
2633 gemPortID := -1
2634 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002635 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302636 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302637 return olterrors.NewErrNotFound("nni-intreface-id",
2638 log.Fields{
2639 "classifier": classifier,
2640 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002641 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302642 }
2643
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002644 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002645 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002646 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002647 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002648
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002649 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2650 log.Fields{
2651 "classifier": classifier,
2652 "action": action,
2653 "flowId": logicalFlow.Id,
2654 "intf-id": networkInterfaceID})
2655
David K. Bainbridge794735f2020-02-11 21:01:37 -08002656 classifierProto, err := makeOpenOltClassifierField(classifier)
2657 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002658 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002659 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002660 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002661 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002662 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002663 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002664 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002665 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002666 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2667 OnuId: int32(onuID), // OnuId not required
2668 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002669 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002670 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002671 AllocId: int32(allocID), // AllocId not used
2672 NetworkIntfId: int32(networkInterfaceID),
2673 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002674 Classifier: classifierProto,
2675 Action: actionProto,
2676 Priority: int32(logicalFlow.Priority),
2677 Cookie: logicalFlow.Cookie,
2678 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002679 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002680 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002681 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002682 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002683 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002684}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002685
Esin Karamanae41e2b2019-12-17 18:13:13 +00002686//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2687func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2688 var packetType string
2689 ovid, ivid := false, false
2690 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2691 vid := vlanID & VlanvIDMask
2692 if vid != ReservedVlan {
2693 ovid = true
2694 }
2695 }
2696 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2697 vid := uint32(metadata)
2698 if vid != ReservedVlan {
2699 ivid = true
2700 }
2701 }
2702 if ovid && ivid {
2703 packetType = DoubleTag
2704 } else if !ovid && !ivid {
2705 packetType = Untagged
2706 } else {
2707 packetType = SingleTag
2708 }
2709 return packetType
2710}
2711
2712//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002713func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002714 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002715 action := make(map[string]interface{})
2716 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2717 action[TrapToHost] = true
2718 /* We manage flowId resource pool on per PON port basis.
2719 Since this situation is tricky, as a hack, we pass the NNI port
2720 index (network_intf_id) as PON port Index for the flowId resource
2721 pool. Also, there is no ONU Id available for trapping packets
2722 on NNI port, use onu_id as -1 (invalid)
2723 ****************** CAVEAT *******************
2724 This logic works if the NNI Port Id falls within the same valid
2725 range of PON Port Ids. If this doesn't work for some OLT Vendor
2726 we need to have a re-look at this.
2727 *********************************************
2728 */
2729 onuID := -1
2730 uniID := -1
2731 gemPortID := -1
2732 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002733 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002734 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302735 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002736 "classifier": classifier,
2737 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002738 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002739 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002740 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002741 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002742 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002743 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002744
David K. Bainbridge794735f2020-02-11 21:01:37 -08002745 classifierProto, err := makeOpenOltClassifierField(classifier)
2746 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002747 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002748 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002749 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002750 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002751 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002752 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002753 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002754 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002755 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2756 OnuId: int32(onuID), // OnuId not required
2757 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002758 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002759 FlowType: Downstream,
2760 AllocId: int32(allocID), // AllocId not used
2761 NetworkIntfId: int32(networkInterfaceID),
2762 GemportId: int32(gemPortID), // GemportId not used
2763 Classifier: classifierProto,
2764 Action: actionProto,
2765 Priority: int32(logicalFlow.Priority),
2766 Cookie: logicalFlow.Cookie,
2767 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002768 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002769 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002770 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002771 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002772
David K. Bainbridge794735f2020-02-11 21:01:37 -08002773 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002774}
2775
salmansiddiqui7ac62132019-08-22 03:58:50 +00002776func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2777 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302778 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002779 }
2780 if Dir == tp_pb.Direction_UPSTREAM {
2781 return "upstream", nil
2782 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2783 return "downstream", nil
2784 }
2785 return "", nil
2786}
2787
Kent Hagermane6ff1012020-07-14 15:07:53 -04002788// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302789func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002790 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002791 tpID uint32, uni string) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002792 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002793 intfID := args[IntfID]
2794 onuID := args[OnuID]
2795 uniID := args[UniID]
2796 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002797 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002798 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002799 gemToAes := make(map[uint32]bool)
2800
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002801 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002802 var direction = tp_pb.Direction_UPSTREAM
2803 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002804 case *tp_pb.TechProfileInstance:
Gamze Abaka7650be62021-02-26 10:50:36 +00002805 if IsUpstream(actionInfo[Output].(uint32)) {
2806 attributes = TpInst.UpstreamGemPortAttributeList
2807 } else {
2808 attributes = TpInst.DownstreamGemPortAttributeList
2809 direction = tp_pb.Direction_DOWNSTREAM
2810 }
2811 default:
2812 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
2813 return
2814 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002815
2816 if len(gemPorts) == 1 {
2817 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002818 gemPortID = gemPorts[0]
2819 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002820 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2821 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002822 pBitMap := attributes[idx].PbitMap
2823 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2824 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2825 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
2826 // this pcp bit traffic.
2827 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2828 if pbitSet == pbit1 {
2829 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2830 pbitToGem[pcp] = gemID
2831 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002832 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002833 }
2834 }
2835 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002836 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2837 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2838 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002839 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002840 }
2841
Gamze Abaka7650be62021-02-26 10:50:36 +00002842 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2843 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2844
salmansiddiqui7ac62132019-08-22 03:58:50 +00002845 if ipProto, ok := classifierInfo[IPProto]; ok {
2846 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002847 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002848 "tp-id": tpID,
2849 "alloc-id": allocID,
2850 "intf-id": intfID,
2851 "onu-id": onuID,
2852 "uni-id": uniID,
2853 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002854 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002855 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002856 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002857 }
2858
Girish Gowdra32625212020-04-29 11:26:35 -07002859 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002860 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302861 log.Fields{
2862 "intf-id": intfID,
2863 "onu-id": onuID,
2864 "uni-id": uniID,
2865 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002866 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002867 logger.Warn(ctx, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002868 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002869 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002870 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002871 return
2872 }
2873 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002874 if ethType.(uint32) == EapEthType {
2875 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002876 "intf-id": intfID,
2877 "onu-id": onuID,
2878 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002879 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002880 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002881 var vlanID uint32
2882 if val, ok := classifierInfo[VlanVid]; ok {
2883 vlanID = (val.(uint32)) & VlanvIDMask
2884 } else {
2885 vlanID = DefaultMgmtVlan
2886 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002887 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002888 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002889 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002890 } else if ethType.(uint32) == PPPoEDEthType {
2891 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2892 "tp-id": tpID,
2893 "alloc-id": allocID,
2894 "intf-id": intfID,
2895 "onu-id": onuID,
2896 "uni-id": uniID,
2897 })
2898 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002899 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002900 logger.Warn(ctx, err)
2901 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002902 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002903 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002904 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002905 "intf-id": intfID,
2906 "onu-id": onuID,
2907 "uni-id": uniID,
2908 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002909 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002910 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002911 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002912 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002913 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002914 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002915 "intf-id": intfID,
2916 "onu-id": onuID,
2917 "uni-id": uniID,
2918 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002919 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002920 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002921 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002922 }
2923 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002924 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05302925 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002926 "intf-id": intfID,
2927 "onu-id": onuID,
2928 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05302929 "classifier": classifierInfo,
2930 "action": actionInfo,
2931 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002932 return
2933 }
2934 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002935 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002936 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002937 logger.Warn(ctx, err)
2938 }
2939 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002940}
2941
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002942func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002943 f.gemToFlowIDsKey.RLock()
2944 flowIDList := f.gemToFlowIDs[gemPortID]
2945 f.gemToFlowIDsKey.RUnlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002946 return len(flowIDList) > 1
2947
Gamze Abakafee36392019-10-03 11:17:24 +00002948}
2949
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002950func (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 +05302951 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002952 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2953 for _, currentGemPort := range currentGemPorts {
2954 for _, tpGemPort := range tpGemPorts {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002955 if (currentGemPort == tpGemPort.GemportId) && (currentGemPort != gemPortID) {
Gamze Abakafee36392019-10-03 11:17:24 +00002956 return true, currentGemPort
2957 }
2958 }
2959 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00002960 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
2961 return false, 0
2962}
Girish Gowdra54934262019-11-13 14:19:55 +05302963
Gamze Abakacb0e6772021-06-10 08:32:12 +00002964func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002965 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
2966 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
2967 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 +00002968 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05302969 for i := 0; i < len(tpInstances); i++ {
2970 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00002971 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002972 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Gamze Abakacb0e6772021-06-10 08:32:12 +00002973 logger.Debugw(ctx, "alloc-is-in-use",
2974 log.Fields{
2975 "device-id": f.deviceHandler.device.Id,
2976 "intfID": sq.intfID,
2977 "onuID": sq.onuID,
2978 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002979 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00002980 })
2981 return true
Girish Gowdra54934262019-11-13 14:19:55 +05302982 }
2983 }
2984 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00002985 return false
Gamze Abakafee36392019-10-03 11:17:24 +00002986}
2987
Neha Sharma96b7bf22020-06-15 10:37:32 +00002988func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002989 for _, field := range flows.GetOfbFields(flow) {
2990 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002991 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002992 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002993 } else if field.Type == flows.ETH_DST {
2994 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002995 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07002996 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002997 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002998 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002999 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003000 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003001 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003002 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05303003 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003004 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003005 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003006 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003007 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003008 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003009 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003010 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003011 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003012 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003013 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003014 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003015 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003016 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003017 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003018 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003019 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003020 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003021 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003022 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003023 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003024 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003025 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003026 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003027 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003028 return
3029 }
3030 }
3031}
3032
Neha Sharma96b7bf22020-06-15 10:37:32 +00003033func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003034 for _, action := range flows.GetActions(flow) {
3035 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003036 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003037 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003038 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003039 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003040 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003041 }
Scott Baker355d1742019-10-24 10:57:52 -07003042 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003043 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003044 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003045 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003046 if out := action.GetPush(); out != nil {
3047 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003048 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003049 } else {
3050 actionInfo[PushVlan] = true
3051 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003052 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303053 log.Fields{
3054 "push-tpid": actionInfo[TPID].(uint32),
3055 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003056 }
3057 }
Scott Baker355d1742019-10-24 10:57:52 -07003058 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003059 if out := action.GetSetField(); out != nil {
3060 if field := out.GetField(); field != nil {
3061 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003062 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003063 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003064 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3065 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003066 }
3067 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003068 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003069 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003070 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003071 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003072 }
3073 }
3074 return nil
3075}
3076
Neha Sharma96b7bf22020-06-15 10:37:32 +00003077func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003078 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003079 fieldtype := ofbField.GetType()
3080 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003081 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3082 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003083 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003084 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003085 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003086 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003087 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3088 pcp := ofbField.GetVlanPcp()
3089 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003090 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003091 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003092 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003093 }
3094 }
3095}
3096
Neha Sharma96b7bf22020-06-15 10:37:32 +00003097func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003098 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003099 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003100 } else {
3101 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003102 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003103 }
3104}
3105
Neha Sharma96b7bf22020-06-15 10:37:32 +00003106func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003107 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003108 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003109 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3110 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003111 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003112 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003113 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303114 log.Fields{
3115 "newinport": classifierInfo[InPort].(uint32),
3116 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003117 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303118 return olterrors.NewErrNotFound("child-in-port",
3119 log.Fields{
3120 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3121 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003122 }
3123 }
3124 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003125 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003126 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003127 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003128 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003129 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003130 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303131 log.Fields{
3132 "newoutport": actionInfo[Output].(uint32),
3133 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003134 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303135 return olterrors.NewErrNotFound("out-port",
3136 log.Fields{
3137 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3138 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003139 }
3140 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3141 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003142 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003143 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003144 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303145 log.Fields{
3146 "newinport": actionInfo[Output].(uint32),
3147 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003148 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303149 return olterrors.NewErrNotFound("nni-port",
3150 log.Fields{
3151 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3152 "in-port": classifierInfo[InPort].(uint32),
3153 "out-port": actionInfo[Output].(uint32),
3154 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003155 }
3156 }
3157 }
3158 return nil
3159}
Gamze Abakafee36392019-10-03 11:17:24 +00003160
Neha Sharma96b7bf22020-06-15 10:37:32 +00003161func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003162 /* Metadata 8 bytes:
3163 Most Significant 2 Bytes = Inner VLAN
3164 Next 2 Bytes = Tech Profile ID(TPID)
3165 Least Significant 4 Bytes = Port ID
3166 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3167 subscriber related flows.
3168 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003169 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003170 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003171 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003172 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003173 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003174 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003175}
3176
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003177func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3178 for _, sliceElement := range slice {
3179 if sliceElement == item {
3180 return slice
3181 }
3182 }
3183 return append(slice, item)
3184}
3185
3186func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003187 for _, sliceElement := range slice {
3188 if sliceElement == item {
3189 return slice
3190 }
3191 }
3192 return append(slice, item)
3193}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303194
3195// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003196func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303197
3198 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3199 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003200 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003201 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003202 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003203 log.Fields{
3204 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003205 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003206 return uint32(0), err
3207 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003208 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303209 return intfID, nil
3210 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003211 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003212 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003213 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003214 log.Fields{
3215 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003216 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003217 return uint32(0), err
3218 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003219 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303220 return intfID, nil
3221 }
3222 return uint32(0), nil
3223}
3224
3225// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003226func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3227 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3228 if err != nil {
3229 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3230 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3231 return
3232 }
3233 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003234
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003235 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003236 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003237 f.packetInGemPortLock.RUnlock()
3238
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303239 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003240 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003241 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 +05303242 log.Fields{
3243 "pktinkey": pktInkey,
3244 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003245 return
3246 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303247 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003248 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003249 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003250 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003251
npujarec5762e2020-01-01 14:08:48 +05303252 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003253 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 +05303254 log.Fields{
3255 "pktinkey": pktInkey,
3256 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303257}
3258
Esin Karaman7fb80c22020-07-16 14:23:33 +00003259//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3260func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3261 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003262 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003263 return 0, 0, errors.New("invalid packet length")
3264 }
3265 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3266 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3267
3268 var index int8
3269 if outerEthType == 0x8100 {
3270 if innerEthType == 0x8100 {
3271 // q-in-q 802.1ad or 802.1q double tagged packet.
3272 // get the inner vlanId
3273 index = 18
3274 } else {
3275 index = 14
3276 }
3277 priority := (packet[index] >> 5) & 0x7
3278 //13 bits composes vlanId value
3279 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3280 return vlan, priority, nil
3281 }
3282 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3283 return 0, 0, nil
3284}
3285
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003286func (f *OpenOltFlowMgr) loadFlowIDsForGemAndGemIDsForFlow(ctx context.Context) {
3287 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - start")
3288 f.onuGemInfoLock.RLock()
3289 f.gemToFlowIDsKey.Lock()
3290 f.flowIDToGemsLock.Lock()
3291 for _, og := range f.onuGemInfoMap {
3292 for _, gem := range og.GemPorts {
3293 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, f.ponPortIdx, gem)
Gamze Abaka3e268512021-09-08 01:14:33 +00003294 if err == nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003295 f.gemToFlowIDs[gem] = flowIDs
3296 for _, flowID := range flowIDs {
3297 if _, ok := f.flowIDToGems[flowID]; !ok {
3298 f.flowIDToGems[flowID] = []uint32{gem}
3299 } else {
3300 f.flowIDToGems[flowID] = appendUnique32bit(f.flowIDToGems[flowID], gem)
3301 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303302 }
3303 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303304 }
3305 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003306 f.flowIDToGemsLock.Unlock()
3307 f.gemToFlowIDsKey.Unlock()
3308 f.onuGemInfoLock.RUnlock()
3309 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - end")
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303310}
Esin Karamanccb714b2019-11-29 15:02:06 +00003311
Girish Gowdra9602eb42020-09-09 15:50:39 -07003312//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3313// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003314func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003315 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003316 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3317 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003318 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003319 "flow-id": flow.Id,
3320 "device-id": f.deviceHandler.device.Id})
3321 // Remove from device
3322 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3323 // DKB
3324 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3325 log.Fields{
3326 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003327 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003328 return err
3329 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003330
3331 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003332}
3333
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003334func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, ponID uint32, onuID uint32, uniID uint32) *ic.InterAdapterTechProfileDownloadMessage {
3335 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003336 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003337 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
3338 return nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003339 }
3340
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003341 switch tpInst := tpInst.(type) {
3342 case *tp_pb.TechProfileInstance:
3343 logger.Debugw(ctx, "fetched-tp-instance-successfully--formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
3344 return &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID,
3345 TpInstancePath: tpPath,
3346 TechTpInstance: &ic.InterAdapterTechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003347 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003348 case *openoltpb2.EponTechProfileInstance:
3349 return &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID,
3350 TpInstancePath: tpPath,
3351 TechTpInstance: &ic.InterAdapterTechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
3352 }
3353 default:
3354 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003355 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003356 return nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003357}
3358
Girish Gowdrabcf98af2021-07-01 08:24:42 -07003359func (f *OpenOltFlowMgr) getOnuGemInfoList(ctx context.Context) []rsrcMgr.OnuGemInfo {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003360 var onuGemInfoLst []rsrcMgr.OnuGemInfo
3361 f.onuGemInfoLock.RLock()
3362 defer f.onuGemInfoLock.RUnlock()
3363 for _, v := range f.onuGemInfoMap {
3364 onuGemInfoLst = append(onuGemInfoLst, *v)
3365 }
3366 return onuGemInfoLst
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003367}