blob: 26973bacba4ecb8d923c75c2c25918c1fc04bfbd [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)
Girish Gowdrada69ec12021-11-16 15:04:58 -0800222 incomingFlows []chan flowControlBlock
223 stopFlowHandlerRoutine []chan bool
224 flowHandlerRoutineActive []bool
manikkaraj kbf256be2019-03-25 00:13:48 +0530225}
226
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700227//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700228func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000229 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530230 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530231 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530232
manikkaraj kbf256be2019-03-25 00:13:48 +0530233 flowMgr.deviceHandler = dh
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700234 flowMgr.ponPortIdx = ponPortIdx
Girish Gowdra9602eb42020-09-09 15:50:39 -0700235 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530236 flowMgr.resourceMgr = rMgr
Neha Sharma96b7bf22020-06-15 10:37:32 +0000237 if err = flowMgr.populateTechProfilePerPonPort(ctx); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700238 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"err": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530239 return nil
240 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700241 flowMgr.gemToFlowIDs = make(map[uint32][]uint64)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530242 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700243 flowMgr.flowIDToGems = make(map[uint64][]uint32)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700244
245 // Create a slice of buffered channels for handling concurrent flows per ONU.
246 // The additional entry (+1) is to handle the NNI trap flows on a separate channel from individual ONUs channel
247 flowMgr.incomingFlows = make([]chan flowControlBlock, MaxOnusPerPon+1)
Girish Gowdrada69ec12021-11-16 15:04:58 -0800248 flowMgr.stopFlowHandlerRoutine = make([]chan bool, MaxOnusPerPon+1)
249 flowMgr.flowHandlerRoutineActive = make([]bool, MaxOnusPerPon+1)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700250 for i := range flowMgr.incomingFlows {
251 flowMgr.incomingFlows[i] = make(chan flowControlBlock, maxConcurrentFlowsPerOnu)
Girish Gowdra0c9ac292021-11-22 14:34:40 -0800252 flowMgr.stopFlowHandlerRoutine[i] = make(chan bool)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700253 // Spin up a go routine to handling incoming flows (add/remove).
254 // There will be on go routine per ONU.
255 // This routine will be blocked on the flowMgr.incomingFlows[onu-id] channel for incoming flows.
Girish Gowdrada69ec12021-11-16 15:04:58 -0800256 flowMgr.flowHandlerRoutineActive[i] = true
257 go flowMgr.perOnuFlowHandlerRoutine(i, flowMgr.incomingFlows[i], flowMgr.stopFlowHandlerRoutine[i])
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700258 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700259 flowMgr.onuGemInfoMap = make(map[uint32]*rsrcMgr.OnuGemInfo)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530260 //Load the onugem info cache from kv store on flowmanager start
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700261 onuIDStart := flowMgr.deviceHandler.deviceInfo.OnuIdStart
262 onuIDEnd := flowMgr.deviceHandler.deviceInfo.OnuIdEnd
263 for onuID := onuIDStart; onuID <= onuIDEnd; onuID++ {
264 // 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 +0000265 onugem, err := rMgr.GetOnuGemInfo(ctx, ponPortIdx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700266 if err == nil && onugem != nil && onugem.SerialNumber != "" {
267 flowMgr.onuGemInfoMap[onuID] = onugem
268 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530269 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700270
271 //Load flowID list per gem map And gemIDs per flow per interface from the kvstore.
272 flowMgr.loadFlowIDsForGemAndGemIDsForFlow(ctx)
273
Esin Karamanccb714b2019-11-29 15:02:06 +0000274 //load interface to multicast queue map from kv store
Girish Gowdra9602eb42020-09-09 15:50:39 -0700275 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000276 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530277 return &flowMgr
278}
279
Kent Hagermane6ff1012020-07-14 15:07:53 -0400280func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700281 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
282 // 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 -0700283 return f.registerFlowIDForGemAndGemIDForFlow(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowFromCore)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700284 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
285 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
286 for _, gemPort := range deviceFlow.PbitToGemport {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700287 if err := f.registerFlowIDForGemAndGemIDForFlow(ctx, uint32(deviceFlow.AccessIntfId), gemPort, flowFromCore); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700288 return err
289 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700290 }
Gamze Abakafee36392019-10-03 11:17:24 +0000291 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700292 return nil
293}
294
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700295func (f *OpenOltFlowMgr) registerFlowIDForGemAndGemIDForFlow(ctx context.Context, accessIntfID uint32, gemPortID uint32, flowFromCore *ofp.OfpFlowStats) error {
296 // update gem->flows map
297 f.gemToFlowIDsKey.Lock()
298 flowIDList, ok := f.gemToFlowIDs[gemPortID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700299 if !ok {
300 flowIDList = []uint64{flowFromCore.Id}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700301 } else {
302 flowIDList = appendUnique64bit(flowIDList, flowFromCore.Id)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700303 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700304 f.gemToFlowIDs[gemPortID] = flowIDList
305 f.gemToFlowIDsKey.Unlock()
306
307 // update flow->gems map
308 f.flowIDToGemsLock.Lock()
309 if _, ok := f.flowIDToGems[flowFromCore.Id]; !ok {
310 f.flowIDToGems[flowFromCore.Id] = []uint32{gemPortID}
311 } else {
312 f.flowIDToGems[flowFromCore.Id] = appendUnique32bit(f.flowIDToGems[flowFromCore.Id], gemPortID)
313 }
314 f.flowIDToGemsLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700315
316 // update the flowids for a gem to the KVstore
317 return f.resourceMgr.UpdateFlowIDsForGem(ctx, accessIntfID, gemPortID, flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400318}
319
Girish Gowdra9602eb42020-09-09 15:50:39 -0700320func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000321 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
Andrea Campanellabfe08432020-09-11 17:07:03 +0200322 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000323 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530324 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700325 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530326
Neha Sharma96b7bf22020-06-15 10:37:32 +0000327 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530328 "device-id": f.deviceHandler.device.Id,
329 "intf-id": intfID,
330 "onu-id": onuID,
331 "uni-id": uniID,
332 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700333 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530334 "action": actionInfo,
335 "usmeter-iD": UsMeterID,
336 "dsmeter-iD": DsMeterID,
337 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400338 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
339 // is because the flow is an NNI flow and there would be no onu resources associated with it
340 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400341 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200342 cause := "no-onu-id-for-flow"
343 fields := log.Fields{
344 "onu": onuID,
345 "port-no": portNo,
346 "classifer": classifierInfo,
347 "action": actionInfo,
348 "device-id": f.deviceHandler.device.Id}
349 logger.Errorw(ctx, cause, fields)
350 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530351 }
352
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700353 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000354 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530355 "uni": uni,
356 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530357
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700358 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
359 "device-id": f.deviceHandler.device.Id,
360 "intf-id": intfID,
361 "onu-id": onuID,
362 "uni-id": uniID,
363 "port-no": portNo,
364 "classifier": classifierInfo,
365 "action": actionInfo,
366 "usmeter-id": UsMeterID,
367 "dsmeter-id": DsMeterID,
368 "tp-id": TpID})
369 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
370 if allocID == 0 || gemPorts == nil || TpInst == nil {
371 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
372 return olterrors.NewErrNotFound(
373 "alloc-id-gem-ports-tp-unavailable",
374 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400375 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700376 args := make(map[string]uint32)
377 args[IntfID] = intfID
378 args[OnuID] = onuID
379 args[UniID] = uniID
380 args[PortNo] = portNo
381 args[AllocID] = allocID
382
383 /* Flows can be added specific to gemport if p-bits are received.
384 * If no pbit mentioned then adding flows for all gemports
385 */
386 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
387
Andrea Campanellabfe08432020-09-11 17:07:03 +0200388 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530389}
390
salmansiddiqui7ac62132019-08-22 03:58:50 +0000391// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530392func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400393
Neha Sharma96b7bf22020-06-15 10:37:32 +0000394 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530395 log.Fields{"dir": sq.direction,
396 "intf-id": sq.intfID,
397 "onu-id": sq.onuID,
398 "uni-id": sq.uniID,
399 "tp-id": sq.tpID,
400 "meter-id": sq.meterID,
401 "tp-inst": sq.tpInst,
402 "flowmetadata": sq.flowMetadata,
403 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400404
Gamze Abakafee36392019-10-03 11:17:24 +0000405 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000406 if err != nil {
407 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400408 }
409
410 /* Lets make a simple assumption that if the meter-id is present on the KV store,
411 * then the scheduler and queues configuration is applied on the OLT device
412 * in the given direction.
413 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000414
Manikkaraj kb1d51442019-07-23 10:41:02 -0400415 var SchedCfg *tp_pb.SchedulerConfig
Girish Gowdraa482f272021-03-24 23:04:19 -0700416 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400417 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530418 return olterrors.NewErrNotFound("meter",
419 log.Fields{"intf-id": sq.intfID,
420 "onu-id": sq.onuID,
421 "uni-id": sq.uniID,
422 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400423 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000424
Girish Gowdraa482f272021-03-24 23:04:19 -0700425 if meterInfo != nil {
426 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 -0700427 if meterInfo.MeterID == sq.meterID {
Girish Gowdraa482f272021-03-24 23:04:19 -0700428 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, true); err != nil {
429 return err
430 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400431 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400432 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530433 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800434 "unsupported": "meter-id",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700435 "kv-store-meter-id": meterInfo.MeterID,
Shrey Baid26912972020-04-16 21:02:31 +0530436 "meter-id-in-flow": sq.meterID,
437 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400438 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000439
Neha Sharma96b7bf22020-06-15 10:37:32 +0000440 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530441 log.Fields{
442 "meter-id": sq.meterID,
443 "direction": Direction,
444 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000445
Gamze Abakafee36392019-10-03 11:17:24 +0000446 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700447 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Gamze Abakafee36392019-10-03 11:17:24 +0000448 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700449 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Girish Kumar8f73fe02019-12-09 13:19:37 +0000450 }
451
Girish Gowdraa482f272021-03-24 23:04:19 -0700452 found := false
453 meterInfo = &rsrcMgr.MeterInfo{}
Gamze Abakafee36392019-10-03 11:17:24 +0000454 if sq.flowMetadata != nil {
455 for _, meter := range sq.flowMetadata.Meters {
456 if sq.meterID == meter.MeterId {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700457 meterInfo.MeterID = meter.MeterId
Girish Gowdraa482f272021-03-24 23:04:19 -0700458 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 +0000459 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700460 log.Fields{"meter": meter,
Shrey Baid26912972020-04-16 21:02:31 +0530461 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -0700462 found = true
Manikkaraj kb1d51442019-07-23 10:41:02 -0400463 break
464 }
465 }
466 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000467 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400468 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700469 if !found {
Thomas Lee S94109f12020-03-03 16:39:29 +0530470 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800471 "reason": "Could-not-get-meterbands-from-flowMetadata",
472 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530473 "meter-id": sq.meterID,
474 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400475 }
Gamze Abaka01174422021-03-10 06:55:27 +0000476
477 var TrafficShaping *tp_pb.TrafficShapingInfo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700478 if TrafficShaping, err = meters.GetTrafficShapingInfo(ctx, sq.flowMetadata.Meters[0]); err != nil {
Gamze Abaka01174422021-03-10 06:55:27 +0000479 return olterrors.NewErrInvalidValue(log.Fields{
480 "reason": "invalid-meter-config",
481 "meter-id": sq.meterID,
482 "device-id": f.deviceHandler.device.Id}, nil)
483 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400484
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700485 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000486 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400487
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700488 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530489 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
490 log.Fields{"intf-id": sq.intfID,
491 "direction": sq.direction,
492 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400493 }
494
salmansiddiqui7ac62132019-08-22 03:58:50 +0000495 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400496 * store the meter id on the KV store, for further reference.
497 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700498 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 +0530499 return olterrors.NewErrAdapter("failed-updating-meter-id",
500 log.Fields{"onu-id": sq.onuID,
501 "meter-id": sq.meterID,
502 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400503 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000504 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530505 log.Fields{"direction": Direction,
Girish Gowdraa482f272021-03-24 23:04:19 -0700506 "meter-info": meterInfo,
507 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400508 return nil
509}
510
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700511func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700512 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000513
514 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530515 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
516 log.Fields{"intf-id": sq.intfID,
517 "direction": sq.direction,
518 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000519 }
520
Gamze Abakacb0e6772021-06-10 08:32:12 +0000521 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
522 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
523 log.Fields{
524 "direction": sq.direction,
525 "TrafficScheds": TrafficSched,
526 "device-id": f.deviceHandler.device.Id,
527 "intfID": sq.intfID,
528 "onuID": sq.onuID,
529 "uniID": sq.uniID})
530 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
531 IntfId: sq.intfID, OnuId: sq.onuID,
532 UniId: sq.uniID, PortNo: sq.uniPort,
533 TrafficScheds: TrafficSched}); err != nil {
534 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
535 }
536 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
537 "direction": sq.direction,
538 "traffic-queues": trafficQueues,
539 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000540 }
541
542 // On receiving the CreateTrafficQueues request, the driver should create corresponding
543 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000544 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530545 log.Fields{"direction": sq.direction,
546 "traffic-queues": trafficQueues,
547 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530548 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000549 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
550 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000551 TrafficQueues: trafficQueues,
552 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530553 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000554 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000555 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530556 "direction": sq.direction,
557 "traffic-queues": trafficQueues,
558 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000559
Esin Karamanccb714b2019-11-29 15:02:06 +0000560 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700561 multicastTrafficQueues := f.techprofile.GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance))
Esin Karamanccb714b2019-11-29 15:02:06 +0000562 if len(multicastTrafficQueues) > 0 {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700563 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 +0000564 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
565 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000566 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000567 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700568 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000569 gemPortID: multicastQueuePerPonPort.GemportId,
570 servicePriority: multicastQueuePerPonPort.Priority,
571 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700572 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000573 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400574 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700575 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400576 return err
577 }
Shrey Baid26912972020-04-16 21:02:31 +0530578
Neha Sharma96b7bf22020-06-15 10:37:32 +0000579 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000580 }
581 }
582 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000583 return nil
584}
585
salmansiddiqui7ac62132019-08-22 03:58:50 +0000586// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530587func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400588
589 var Direction string
590 var SchedCfg *tp_pb.SchedulerConfig
591 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000592 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530593 log.Fields{
594 "direction": sq.direction,
595 "intf-id": sq.intfID,
596 "onu-id": sq.onuID,
597 "uni-id": sq.uniID,
598 "uni-port": sq.uniPort,
599 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000600 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700601 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400602 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000603 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700604 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400605 Direction = "downstream"
606 }
607
Girish Gowdraa482f272021-03-24 23:04:19 -0700608 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 -0400609
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700610 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000611 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000612
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700613 TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000614 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530615 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
616 log.Fields{
617 "intf-id": sq.intfID,
618 "direction": sq.direction,
619 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000620 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400621
npujarec5762e2020-01-01 14:08:48 +0530622 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000623 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
624 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000625 TrafficQueues: TrafficQueues,
626 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000627 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530628 log.Fields{
629 "intf-id": sq.intfID,
630 "traffic-queues": TrafficQueues,
631 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400632 }
Gamze Abakacb0e6772021-06-10 08:32:12 +0000633 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id, "trafficQueues": TrafficQueues})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400634
Gamze Abakacb0e6772021-06-10 08:32:12 +0000635 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
636 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
637 IntfId: sq.intfID, OnuId: sq.onuID,
638 UniId: sq.uniID, PortNo: sq.uniPort,
639 TrafficScheds: TrafficSched}); err != nil {
640 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
641 log.Fields{
642 "intf-id": sq.intfID,
643 "traffic-schedulers": TrafficSched,
644 "onu-id": sq.onuID,
645 "uni-id": sq.uniID,
646 "uni-port": sq.uniPort}, err)
647 }
648
649 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
650 log.Fields{"device-id": f.deviceHandler.device.Id,
651 "intf-id": sq.intfID,
652 "onu-id": sq.onuID,
653 "uni-id": sq.uniID,
654 "uni-port": sq.uniPort})
655
656 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700657 allocID := sq.tpInst.(*tp_pb.TechProfileInstance).UsScheduler.AllocId
Gamze Abakacb0e6772021-06-10 08:32:12 +0000658 f.resourceMgr.FreeAllocID(ctx, sq.intfID, sq.onuID, sq.uniID, allocID)
659 // Delete the TCONT on the ONU.
660 uni := getUniPortPath(f.deviceHandler.device.Id, sq.intfID, int32(sq.onuID), int32(sq.uniID))
661 tpPath := f.getTPpath(ctx, sq.intfID, uni, sq.tpID)
662 if err := f.sendDeleteTcontToChild(ctx, sq.intfID, sq.onuID, sq.uniID, allocID, tpPath); err != nil {
663 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
664 log.Fields{
665 "intf": sq.intfID,
666 "onu-id": sq.onuID,
667 "uni-id": sq.uniID,
668 "device-id": f.deviceHandler.device.Id,
669 "alloc-id": allocID})
670 }
671 }
672 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000673
674 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400675 * delete the meter id on the KV store.
676 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700677 err = f.resourceMgr.RemoveMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400678 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530679 return olterrors.NewErrAdapter("unable-to-remove-meter",
680 log.Fields{
681 "onu": sq.onuID,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700682 "device-id": f.deviceHandler.device.Id,
683 "intf-id": sq.intfID,
684 "onu-id": sq.onuID,
685 "uni-id": sq.uniID,
686 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400687 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000688 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530689 log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530690 "dir": Direction,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700691 "device-id": f.deviceHandler.device.Id,
692 "intf-id": sq.intfID,
693 "onu-id": sq.onuID,
694 "uni-id": sq.uniID,
695 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400696 return err
697}
698
Girish Gowdra37f13fa2021-08-16 10:59:45 -0700699// We are trying to force remove the schedulers and queues here if one exists for the given key.
700// We ignore any errors encountered in the process. The errors most likely are encountered when
701// the schedulers and queues are already cleared for the given key.
702func (f *OpenOltFlowMgr) forceRemoveSchedulerQueues(ctx context.Context, sq schedQueue) {
703
704 var schedCfg *tp_pb.SchedulerConfig
705 var err error
706 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
707 log.Fields{
708 "direction": sq.direction,
709 "intf-id": sq.intfID,
710 "onu-id": sq.onuID,
711 "uni-id": sq.uniID,
712 "uni-port": sq.uniPort,
713 "tp-id": sq.tpID,
714 "device-id": f.deviceHandler.device.Id})
715 if sq.direction == tp_pb.Direction_UPSTREAM {
716 schedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
717 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
718 schedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
719 }
720
721 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
722 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), schedCfg, TrafficShaping)}
723 TrafficSched[0].TechProfileId = sq.tpID
724
725 // Remove traffic queues. Ignore any errors, just log them.
726 if TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction); err != nil {
727 logger.Errorw(ctx, "error retrieving traffic queue", log.Fields{
728 "direction": sq.direction,
729 "intf-id": sq.intfID,
730 "onu-id": sq.onuID,
731 "uni-id": sq.uniID,
732 "uni-port": sq.uniPort,
733 "tp-id": sq.tpID,
734 "device-id": f.deviceHandler.device.Id,
735 "err": err})
736 } else {
737 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
738 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
739 UniId: sq.uniID, PortNo: sq.uniPort,
740 TrafficQueues: TrafficQueues,
741 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
742 logger.Warnw(ctx, "error removing traffic queue", log.Fields{
743 "direction": sq.direction,
744 "intf-id": sq.intfID,
745 "onu-id": sq.onuID,
746 "uni-id": sq.uniID,
747 "uni-port": sq.uniPort,
748 "tp-id": sq.tpID,
749 "device-id": f.deviceHandler.device.Id,
750 "err": err})
751
752 } else {
753 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
754 "direction": sq.direction,
755 "intf-id": sq.intfID,
756 "onu-id": sq.onuID,
757 "uni-id": sq.uniID,
758 "uni-port": sq.uniPort,
759 "tp-id": sq.tpID})
760 }
761 }
762
763 // Remove traffic schedulers. Ignore any errors, just log them.
764 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
765 IntfId: sq.intfID, OnuId: sq.onuID,
766 UniId: sq.uniID, PortNo: sq.uniPort,
767 TrafficScheds: TrafficSched}); err != nil {
768 logger.Warnw(ctx, "error removing traffic scheduler", log.Fields{
769 "direction": sq.direction,
770 "intf-id": sq.intfID,
771 "onu-id": sq.onuID,
772 "uni-id": sq.uniID,
773 "uni-port": sq.uniPort,
774 "tp-id": sq.tpID,
775 "device-id": f.deviceHandler.device.Id,
776 "err": err})
777 } else {
778 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
779 "direction": sq.direction,
780 "intf-id": sq.intfID,
781 "onu-id": sq.onuID,
782 "uni-id": sq.uniID,
783 "uni-port": sq.uniPort,
784 "tp-id": sq.tpID})
785 }
786}
787
Gamze Abakafee36392019-10-03 11:17:24 +0000788// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700789func (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 +0000790 var allocIDs []uint32
791 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530792 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530793 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000794 var err error
npujarec5762e2020-01-01 14:08:48 +0530795 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
796 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000797 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530798
Neha Sharma96b7bf22020-06-15 10:37:32 +0000799 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530800 "intf-id": intfID,
801 "onu-id": onuID,
802 "uni-id": uniID,
803 "device-id": f.deviceHandler.device.Id,
804 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530805
Manikkaraj kb1d51442019-07-23 10:41:02 -0400806 // Check tech profile instance already exists for derived port name
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700807 techProfileInstance, _ := f.techprofile.GetTPInstance(ctx, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000808 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000809 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530810 log.Fields{
811 "path": tpPath,
812 "device-id": f.deviceHandler.device.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700813 techProfileInstance, err = f.techprofile.CreateTechProfileInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000814 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530815 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000816 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530817 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700818 "err": err,
Shrey Baid26912972020-04-16 21:02:31 +0530819 "tp-id": TpID,
820 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000821 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530822 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400823 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700824 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400825 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530826 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000827 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530828 log.Fields{
829 "uni": uni,
830 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530831 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530832 }
Gamze Abakafee36392019-10-03 11:17:24 +0000833
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700834 switch tpInst := techProfileInstance.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700835 case *tp_pb.TechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700836 if UsMeterID != 0 {
837 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
838 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
839 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000840 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700841 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700842 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700843 "onu-id": onuID,
844 "uni-id": uniID,
845 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700846 "meter-id": UsMeterID,
847 "device-id": f.deviceHandler.device.Id})
848 return 0, nil, nil
849 }
850 }
851 if DsMeterID != 0 {
852 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
853 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
854 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000855 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700856 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700857 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700858 "onu-id": onuID,
859 "uni-id": uniID,
860 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700861 "meter-id": DsMeterID,
862 "device-id": f.deviceHandler.device.Id})
863 return 0, nil, nil
864 }
865 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700866 allocID := tpInst.UsScheduler.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700867 for _, gem := range tpInst.UpstreamGemPortAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700868 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700869 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700870 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000871
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700872 if tpInstanceExists {
873 return allocID, gemPortIDs, techProfileInstance
874 }
875
876 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700877 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700878 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000879 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700880 log.Fields{
Matteo Scandolo84585372021-03-18 14:21:22 -0700881 "intf-id": intfID,
882 "onu-id": onuID,
883 "uni-id": uniID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700884 "alloc-ids": allocIDs,
885 "gemports": allgemPortIDs,
886 "device-id": f.deviceHandler.device.Id})
887 // Send Tconts and GEM ports to KV store
888 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530889 return allocID, gemPortIDs, techProfileInstance
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700890 case *openoltpb2.EponTechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700891 // CreateSchedulerQueues for EPON needs to be implemented here
892 // when voltha-protos for EPON is completed.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700893 allocID := tpInst.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700894 for _, gem := range tpInst.UpstreamQueueAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700895 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700896 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700897 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700898
899 if tpInstanceExists {
900 return allocID, gemPortIDs, techProfileInstance
901 }
902
903 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700904 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700905 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000906 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700907 log.Fields{
908 "alloc-ids": allocIDs,
909 "gemports": allgemPortIDs,
910 "device-id": f.deviceHandler.device.Id})
911 // Send Tconts and GEM ports to KV store
912 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
913 return allocID, gemPortIDs, techProfileInstance
914 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000915 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700916 log.Fields{
917 "tpInst": tpInst})
918 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530919 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530920}
921
npujarec5762e2020-01-01 14:08:48 +0530922func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530923
Neha Sharma96b7bf22020-06-15 10:37:32 +0000924 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530925 log.Fields{
926 "intf-id": intfID,
927 "onu-id": onuID,
928 "uni-id": uniID,
929 "alloc-id": allocID,
930 "gemport-ids": gemPortIDs,
931 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530932 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530933 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000934 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 +0530935 }
npujarec5762e2020-01-01 14:08:48 +0530936 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000937 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 +0530938 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700939
Neha Sharma96b7bf22020-06-15 10:37:32 +0000940 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 -0400941 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530942 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400943 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530944}
945
Neha Sharma96b7bf22020-06-15 10:37:32 +0000946func (f *OpenOltFlowMgr) populateTechProfilePerPonPort(ctx context.Context) error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000947 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530948 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000949 for _, intfID := range techRange.IntfIds {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700950 f.techprofile = f.resourceMgr.PonRsrMgr.TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400951 tpCount++
Neha Sharma96b7bf22020-06-15 10:37:32 +0000952 logger.Debugw(ctx, "init-tech-profile-done",
Shrey Baid26912972020-04-16 21:02:31 +0530953 log.Fields{
954 "intf-id": intfID,
955 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530956 }
957 }
958 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400959 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530960 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530961 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800962 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530963 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
964 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530965 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000966 logger.Infow(ctx, "populated-techprofile-for-ponports-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530967 log.Fields{
968 "numofTech": tpCount,
969 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
970 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530971 return nil
972}
973
Gamze Abaka7650be62021-02-26 10:50:36 +0000974func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
975 flowContext.classifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000976 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530977 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000978 "uplinkClassifier": flowContext.classifier,
979 "uplinkAction": flowContext.action})
980 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
Manikkaraj k884c1242019-04-11 16:26:42 +0530981 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530982}
983
Gamze Abaka7650be62021-02-26 10:50:36 +0000984func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
985 downlinkClassifier := flowContext.classifier
986 downlinkAction := flowContext.action
987
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700988 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000989 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530990 log.Fields{
991 "downlinkClassifier": downlinkClassifier,
992 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400993 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
994 if vlan, exists := downlinkClassifier[VlanVid]; exists {
995 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700996 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Gamze Abaka7650be62021-02-26 10:50:36 +0000997 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, flowContext.intfID, flowContext.onuID, flowContext.uniID) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000998 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530999 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +00001000 "flow": flowContext.logicalFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301001 "device-id": f.deviceHandler.device.Id,
Gamze Abaka7650be62021-02-26 10:50:36 +00001002 "onu-id": flowContext.onuID,
1003 "intf-id": flowContext.intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001004 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -04001005 }
1006 }
1007 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301008 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001009
Manikkaraj k884c1242019-04-11 16:26:42 +05301010 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001011 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -04001012 // vlan_vid is a uint32. must be type asserted as such or conversion fails
1013 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +05301014 if ok {
1015 downlinkAction[VlanVid] = dlClVid & 0xfff
1016 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +05301017 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301018 "reason": "failed-to-convert-vlanid-classifier",
1019 "vlan-id": VlanVid,
1020 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +05301021 }
1022
Gamze Abaka7650be62021-02-26 10:50:36 +00001023 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301024}
1025
Gamze Abaka7650be62021-02-26 10:50:36 +00001026func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001027
Gamze Abaka7650be62021-02-26 10:50:36 +00001028 intfID := flowContext.intfID
1029 onuID := flowContext.onuID
1030 uniID := flowContext.uniID
1031 classifier := flowContext.classifier
1032 action := flowContext.action
1033 allocID := flowContext.allocID
1034 gemPortID := flowContext.gemPortID
1035 tpID := flowContext.tpID
1036 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001037 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301038 log.Fields{
1039 "intf-id": intfID,
1040 "onu-id": onuID,
1041 "uni-id": uniID,
1042 "device-id": f.deviceHandler.device.Id,
1043 "classifier": classifier,
1044 "action": action,
1045 "direction": direction,
1046 "alloc-id": allocID,
1047 "gemport-id": gemPortID,
1048 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001049
1050 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001051 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301052 log.Fields{
1053 "device-id": f.deviceHandler.device.Id,
1054 "intf-id": intfID,
1055 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001056 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301057 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001058 classifierProto, err := makeOpenOltClassifierField(classifier)
1059 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301060 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301061 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001062 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301063 log.Fields{
1064 "classifier": *classifierProto,
1065 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001066 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001067 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301068 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301069 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001070 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301071 log.Fields{
1072 "action": *actionProto,
1073 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001074 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301075 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301076 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001077 log.Fields{
1078 "classifier": classifier,
1079 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301080 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001081 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301082 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001083
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001084 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001085 OnuId: int32(onuID),
1086 UniId: int32(uniID),
1087 FlowId: logicalFlow.Id,
1088 FlowType: direction,
1089 AllocId: int32(allocID),
1090 NetworkIntfId: int32(networkIntfID),
1091 GemportId: int32(gemPortID),
1092 Classifier: classifierProto,
1093 Action: actionProto,
1094 Priority: int32(logicalFlow.Priority),
1095 Cookie: logicalFlow.Cookie,
1096 PortNo: flowContext.portNo,
1097 TechProfileId: tpID,
1098 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1099 PbitToGemport: flowContext.pbitToGem,
1100 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001101 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001102 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001103 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301104 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001105 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301106 log.Fields{"direction": direction,
1107 "device-id": f.deviceHandler.device.Id,
1108 "flow": flow,
1109 "intf-id": intfID,
1110 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001111
David K. Bainbridge794735f2020-02-11 21:01:37 -08001112 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301113}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001114
Gamze Abaka7650be62021-02-26 10:50:36 +00001115func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1116
1117 intfID := flowContext.intfID
1118 onuID := flowContext.onuID
1119 uniID := flowContext.uniID
1120 logicalFlow := flowContext.logicalFlow
1121 classifier := flowContext.classifier
1122 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301123
Neha Sharma96b7bf22020-06-15 10:37:32 +00001124 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301125 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301126 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001127 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301128 "action": action,
1129 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001130 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301131 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301132
1133 // Clear the action map
1134 for k := range action {
1135 delete(action, k)
1136 }
1137
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001138 action[TrapToHost] = true
1139 classifier[UDPSrc] = uint32(68)
1140 classifier[UDPDst] = uint32(67)
1141 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301142
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001143 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001144 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301145 log.Fields{
1146 "device-id": f.deviceHandler.device.Id,
1147 "intf-id": intfID,
1148 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001149 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301150 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301151
Neha Sharma96b7bf22020-06-15 10:37:32 +00001152 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301153 log.Fields{
1154 "ul_classifier": classifier,
1155 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001156 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301157 "intf-id": intfID,
1158 "onu-id": onuID,
1159 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301160
David K. Bainbridge794735f2020-02-11 21:01:37 -08001161 classifierProto, err := makeOpenOltClassifierField(classifier)
1162 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301163 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301164 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001165 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001166 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001167 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301168 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301169 }
1170
David K. Bainbridge794735f2020-02-11 21:01:37 -08001171 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001172 OnuId: int32(onuID),
1173 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001174 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001175 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001176 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001177 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001178 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301179 Classifier: classifierProto,
1180 Action: actionProto,
1181 Priority: int32(logicalFlow.Priority),
1182 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001183 PortNo: flowContext.portNo,
1184 TechProfileId: flowContext.tpID,
1185 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1186 PbitToGemport: flowContext.pbitToGem,
1187 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001188 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001189 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001190 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001191 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001192 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301193 log.Fields{
1194 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001195 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301196 "intf-id": intfID,
1197 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301198
David K. Bainbridge794735f2020-02-11 21:01:37 -08001199 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301200}
1201
Esin Karamanae41e2b2019-12-17 18:13:13 +00001202//addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001203func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1204 delete(flowContext.classifier, VlanVid)
1205 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001206}
1207
1208//addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001209func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1210
1211 intfID := flowContext.intfID
1212 onuID := flowContext.onuID
1213 uniID := flowContext.uniID
1214 logicalFlow := flowContext.logicalFlow
1215 classifier := flowContext.classifier
1216 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001217
Neha Sharma96b7bf22020-06-15 10:37:32 +00001218 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001219 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301220 return olterrors.NewErrNotFound("nni-interface-id",
1221 log.Fields{
1222 "classifier": classifier,
1223 "action": action,
1224 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001225 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001226 }
1227
1228 // Clear the action map
1229 for k := range action {
1230 delete(action, k)
1231 }
1232
1233 action[TrapToHost] = true
1234 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001235
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001236 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001237 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001238 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001239 }
1240
Neha Sharma96b7bf22020-06-15 10:37:32 +00001241 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301242 log.Fields{
1243 "ul_classifier": classifier,
1244 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001245 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301246 "device-id": f.deviceHandler.device.Id,
1247 "intf-id": intfID,
1248 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001249
David K. Bainbridge794735f2020-02-11 21:01:37 -08001250 classifierProto, err := makeOpenOltClassifierField(classifier)
1251 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301252 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001253 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001254 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301255 log.Fields{
1256 "classifier": *classifierProto,
1257 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001258 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001259 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301260 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001261 }
1262
David K. Bainbridge794735f2020-02-11 21:01:37 -08001263 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001264 OnuId: int32(onuID),
1265 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001266 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001267 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001268 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001269 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001270 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001271 Classifier: classifierProto,
1272 Action: actionProto,
1273 Priority: int32(logicalFlow.Priority),
1274 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001275 PortNo: flowContext.portNo,
1276 TechProfileId: flowContext.tpID,
1277 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1278 PbitToGemport: flowContext.pbitToGem,
1279 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001280 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001281
David K. Bainbridge794735f2020-02-11 21:01:37 -08001282 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001283 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": flow, "device-id": f.deviceHandler.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001284 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001285
David K. Bainbridge794735f2020-02-11 21:01:37 -08001286 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001287}
1288
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001289// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001290func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1291 intfID := flowContext.intfID
1292 onuID := flowContext.onuID
1293 uniID := flowContext.uniID
1294 portNo := flowContext.portNo
1295 allocID := flowContext.allocID
1296 gemPortID := flowContext.gemPortID
1297 logicalFlow := flowContext.logicalFlow
1298 classifier := flowContext.classifier
1299 action := flowContext.action
1300
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001301 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301302 log.Fields{
1303 "intf-id": intfID,
1304 "onu-id": onuID,
1305 "port-no": portNo,
1306 "alloc-id": allocID,
1307 "gemport-id": gemPortID,
1308 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001309 "flow": logicalFlow,
1310 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301311
1312 uplinkClassifier := make(map[string]interface{})
1313 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301314
manikkaraj kbf256be2019-03-25 00:13:48 +05301315 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001316 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001317 uplinkClassifier[PacketTagType] = SingleTag
1318 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001319 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301320 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001321 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001322 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001323 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301324 "device-id": f.deviceHandler.device.Id,
1325 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001326 "intf-id": intfID,
1327 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001328 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301329 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001330 //Add Uplink EthType Flow
1331 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301332 log.Fields{
1333 "ul_classifier": uplinkClassifier,
1334 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001335 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301336 "device-id": f.deviceHandler.device.Id,
1337 "intf-id": intfID,
1338 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301339
David K. Bainbridge794735f2020-02-11 21:01:37 -08001340 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1341 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301342 return olterrors.NewErrInvalidValue(log.Fields{
1343 "classifier": uplinkClassifier,
1344 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301345 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001346 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301347 log.Fields{
1348 "classifier": *classifierProto,
1349 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001350 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001351 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301352 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301353 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001354 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301355 log.Fields{
1356 "action": *actionProto,
1357 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001358 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301359 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301360 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001361 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301362 "action": action,
1363 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001364 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301365 }
1366
David K. Bainbridge794735f2020-02-11 21:01:37 -08001367 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001368 OnuId: int32(onuID),
1369 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001370 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001371 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001372 AllocId: int32(allocID),
1373 NetworkIntfId: int32(networkIntfID),
1374 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301375 Classifier: classifierProto,
1376 Action: actionProto,
1377 Priority: int32(logicalFlow.Priority),
1378 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001379 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001380 TechProfileId: flowContext.tpID,
1381 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1382 PbitToGemport: flowContext.pbitToGem,
1383 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001384 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001385 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001386 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001387 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001388 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301389 log.Fields{
1390 "device-id": f.deviceHandler.device.Id,
1391 "onu-id": onuID,
1392 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001393 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301394 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001395
David K. Bainbridge794735f2020-02-11 21:01:37 -08001396 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301397}
1398
David K. Bainbridge794735f2020-02-11 21:01:37 -08001399func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001400 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001401
1402 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1403 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1404 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001405 if vlanID != ReservedVlan {
1406 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001407 classifier.OVid = vid
1408 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301409 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001410 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1411 vid := uint32(metadata)
1412 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001413 classifier.IVid = vid
1414 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301415 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301416 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001417 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301418 classifier.OPbits = vlanPcp
1419 } else {
1420 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301421 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001422 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1423 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1424 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1425 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001426 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001427 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1428 classifier.PktTagType = pktTagType
1429
1430 switch pktTagType {
1431 case SingleTag:
1432 case DoubleTag:
1433 case Untagged:
1434 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001435 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301436 }
1437 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001438 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301439}
1440
Gamze Abaka724d0852020-03-18 12:10:24 +00001441func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001442 var actionCmd openoltpb2.ActionCmd
1443 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301444 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001445 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301446 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001447 if _, ok := actionInfo[VlanPcp]; ok {
1448 action.Cmd.RemarkInnerPbits = true
1449 action.IPbits = actionInfo[VlanPcp].(uint32)
1450 if _, ok := actionInfo[VlanVid]; ok {
1451 action.Cmd.TranslateInnerTag = true
1452 action.IVid = actionInfo[VlanVid].(uint32)
1453 }
1454 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001455 } else if _, ok := actionInfo[PushVlan]; ok {
1456 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301457 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001458 if _, ok := actionInfo[VlanPcp]; ok {
1459 action.OPbits = actionInfo[VlanPcp].(uint32)
1460 action.Cmd.RemarkOuterPbits = true
1461 if _, ok := classifierInfo[VlanVid]; ok {
1462 action.IVid = classifierInfo[VlanVid].(uint32)
1463 action.Cmd.TranslateInnerTag = true
1464 }
1465 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001466 } else if _, ok := actionInfo[TrapToHost]; ok {
1467 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301468 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001469 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301470 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001471 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301472}
1473
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001474// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001475func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001476 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301477}
1478
Gamze Abakafee36392019-10-03 11:17:24 +00001479// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdra37f13fa2021-08-16 10:59:45 -07001480// We also force release scheduler and queues associated with the tp instance. Theoretically there could be
1481// an issue if the upstream scheduler (DBA) is shared across multiple UNI and we force release it, given that
1482// this function is only meant to clean up TP instances of a given UNI. But in practicality this routine
1483// is only meant to be called when the clean up of resource for the whole ONU is taking place.
1484// The reason for introducing the force cleanup of scheduler and queues (on the OLT) was introduced here
1485// because it was observed that if the ONU device was deleted too soon after the flows were
1486// unprovisioned on that ONU, the scheduler and queue removal pertinent to that ONU would remain
1487// uncleaned on the OLT. So we force clean up here and ignore any error that OLT returns during the
1488// force cleanup (possible if the OLT has already cleared those resources).
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001489func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301490 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001491 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1492
Gamze Abakafee36392019-10-03 11:17:24 +00001493 for _, tpID := range tpIDList {
Girish Gowdra37f13fa2021-08-16 10:59:45 -07001494
1495 // Force cleanup scheduler/queues -- start
1496 uniPortNum := MkUniPortNum(ctx, intfID, onuID, uniID)
1497 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1498 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
1499 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1500 if err != nil || tpInst == nil { // This should not happen, something wrong in KV backend transaction
1501 logger.Warnw(ctx, "tech-profile-not-in-kv-store",
1502 log.Fields{
1503 "tp-id": tpID,
1504 "path": tpPath})
1505 }
1506 switch tpInstance := tpInst.(type) {
1507 case *tp_pb.TechProfileInstance:
1508 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1509 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1510 }
1511 // Force cleanup scheduler/queues -- end
1512
1513 // Now remove the tp instance
npujarec5762e2020-01-01 14:08:48 +05301514 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001515 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301516 // return err
1517 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001518 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001519 logger.Debugw(ctx, "tech-profile-instance-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "uniPortName": uniPortName, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001520 }
1521 return nil
1522}
1523
1524// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301525func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001526 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001527 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001528 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001529 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301530 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1531 log.Fields{
1532 "tp-id": tpID,
1533 "uni-port-name": uniPortName,
1534 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001535 }
1536 return nil
1537}
1538
David K. Bainbridge794735f2020-02-11 21:01:37 -08001539func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001540
1541 var intfID uint32
1542 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1543 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1544 */
1545 if deviceFlow.AccessIntfId != -1 {
1546 intfID = uint32(deviceFlow.AccessIntfId)
1547 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001548 // We need to log the valid interface ID.
1549 // For trap-on-nni flows, the access_intf_id is invalid (-1), so choose the network_intf_id.
Daniele Rossi22db98e2019-07-11 11:50:00 +00001550 intfID = uint32(deviceFlow.NetworkIntfId)
1551 }
1552
Neha Sharma96b7bf22020-06-15 10:37:32 +00001553 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301554 "flow": *deviceFlow,
1555 "device-id": f.deviceHandler.device.Id,
1556 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001557 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001558
1559 st, _ := status.FromError(err)
1560 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001561 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001562 "err": err,
1563 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301564 "device-id": f.deviceHandler.device.Id,
1565 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001566 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301567 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001568
1569 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001570 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301571 log.Fields{"err": err,
1572 "device-flow": deviceFlow,
1573 "device-id": f.deviceHandler.device.Id,
1574 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001575 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001576 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001577 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301578 log.Fields{
1579 "flow": *deviceFlow,
1580 "device-id": f.deviceHandler.device.Id,
1581 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001582
1583 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1584 if deviceFlow.AccessIntfId != -1 {
1585 // No need to register the flow if it is a trap on nni flow.
1586 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1587 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1588 return err
1589 }
1590 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001591 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001592}
1593
Neha Sharma96b7bf22020-06-15 10:37:32 +00001594func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1595 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301596 log.Fields{
1597 "flow": *deviceFlow,
1598 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001599 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001600 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001601 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001602 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301603 log.Fields{
1604 "err": err,
1605 "deviceFlow": deviceFlow,
1606 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001607 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001608 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001609 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001610 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001611
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001612 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001613 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001614 "of-flow-id": ofFlowID,
1615 "flow": *deviceFlow,
1616 "device-id": f.deviceHandler.device.Id,
1617 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001618 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301619}
1620
David K. Bainbridge794735f2020-02-11 21:01:37 -08001621func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001622
1623 classifierInfo := make(map[string]interface{})
1624 actionInfo := make(map[string]interface{})
1625
1626 classifierInfo[EthType] = uint32(LldpEthType)
1627 classifierInfo[PacketTagType] = Untagged
1628 actionInfo[TrapToHost] = true
1629
1630 // LLDP flow is installed to trap LLDP packets on the NNI port.
1631 // We manage flow_id resource pool on per PON port basis.
1632 // Since this situation is tricky, as a hack, we pass the NNI port
1633 // index (network_intf_id) as PON port Index for the flow_id resource
1634 // pool. Also, there is no ONU Id available for trapping LLDP packets
1635 // on NNI port, use onu_id as -1 (invalid)
1636 // ****************** CAVEAT *******************
1637 // This logic works if the NNI Port Id falls within the same valid
1638 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1639 // we need to have a re-look at this.
1640 // *********************************************
1641
1642 var onuID = -1
1643 var uniID = -1
1644 var gemPortID = -1
1645
Neha Sharma96b7bf22020-06-15 10:37:32 +00001646 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001647 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301648 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001649 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001650 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001651 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001652 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001653 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001654
David K. Bainbridge794735f2020-02-11 21:01:37 -08001655 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1656 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301657 return olterrors.NewErrInvalidValue(
1658 log.Fields{
1659 "classifier": classifierInfo,
1660 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001661 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001662 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301663 log.Fields{
1664 "classifier": *classifierProto,
1665 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001666 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001667 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301668 return olterrors.NewErrInvalidValue(
1669 log.Fields{
1670 "action": actionInfo,
1671 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001672 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001673 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301674 log.Fields{
1675 "action": *actionProto,
1676 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001677
1678 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1679 OnuId: int32(onuID), // OnuId not required
1680 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001681 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001682 FlowType: Downstream,
1683 NetworkIntfId: int32(networkInterfaceID),
1684 GemportId: int32(gemPortID),
1685 Classifier: classifierProto,
1686 Action: actionProto,
1687 Priority: int32(flow.Priority),
1688 Cookie: flow.Cookie,
1689 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001690 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001691 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301692 log.Fields{
1693 "flow": downstreamflow,
1694 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001695 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001696 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301697 log.Fields{
1698 "device-id": f.deviceHandler.device.Id,
1699 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001700 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001701
David K. Bainbridge794735f2020-02-11 21:01:37 -08001702 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301703}
1704
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001705func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1706 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001707}
1708
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001709//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001710func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001711 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1712 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1713 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001714 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301715 log.Fields{
1716 "intf-id": intfID,
1717 "onu-id": onuID,
1718 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001719 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001720 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301721 return nil, olterrors.NewErrNotFound("onu-child-device",
1722 log.Fields{
1723 "onu-id": onuID,
1724 "intf-id": intfID,
1725 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001726 }
1727 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1728 //better to ad the device to cache here.
1729 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1730 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001731 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301732 log.Fields{
1733 "intf-id": intfID,
1734 "onu-id": onuID,
1735 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001736 }
1737
1738 return onuDev.(*OnuDevice), nil
1739}
1740
1741//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001742func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1743 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301744 log.Fields{
1745 "pon-port": intfID,
1746 "onu-id": onuID,
1747 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001748 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001749 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001750 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301751 return nil, olterrors.NewErrNotFound("onu",
1752 log.Fields{
1753 "interface-id": parentPortNo,
1754 "onu-id": onuID,
1755 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001756 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301757 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001758 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301759 log.Fields{
1760 "device-id": f.deviceHandler.device.Id,
1761 "child_device_id": onuDevice.Id,
1762 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301763 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301764}
1765
Neha Sharma96b7bf22020-06-15 10:37:32 +00001766func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1767 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301768 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001769 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301770 log.Fields{
1771 "intf-id": intfID,
1772 "onu-id": onuID,
1773 "uni-id": uniID,
1774 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001775 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301776 }
1777
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001778 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpInstancePath: tpPath, GemPortId: gemPortID}
1779 logger.Infow(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301780 log.Fields{
1781 "msg": *delGemPortMsg,
1782 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001783 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301784 delGemPortMsg,
1785 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001786 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001787 onuDev.deviceType,
1788 onuDev.deviceID,
1789 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301790 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1791 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001792 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301793 "to-adapter": onuDev.deviceType,
1794 "onu-id": onuDev.deviceID,
1795 "proxyDeviceID": onuDev.proxyDeviceID,
1796 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301797 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001798 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301799 log.Fields{
1800 "msg": delGemPortMsg,
1801 "from-adapter": f.deviceHandler.device.Type,
1802 "to-adapter": onuDev.deviceType,
1803 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301804 return nil
1805}
1806
Neha Sharma96b7bf22020-06-15 10:37:32 +00001807func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1808 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301809 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001810 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301811 log.Fields{
1812 "intf-id": intfID,
1813 "onu-id": onuID,
1814 "uni-id": uniID,
1815 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001816 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301817 }
1818
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001819 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpInstancePath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001820 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301821 log.Fields{
1822 "msg": *delTcontMsg,
1823 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001824 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301825 delTcontMsg,
1826 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001827 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001828 onuDev.deviceType,
1829 onuDev.deviceID,
1830 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301831 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1832 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001833 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301834 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1835 "proxyDeviceID": onuDev.proxyDeviceID,
1836 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301837 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001838 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301839 log.Fields{
1840 "msg": delTcontMsg,
1841 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301842 return nil
1843}
1844
Girish Gowdrac3037402020-01-22 20:29:53 +05301845// Once the gemport is released for a given onu, it also has to be cleared from local cache
1846// which was used for deriving the gemport->logicalPortNo during packet-in.
1847// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1848// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001849func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001850 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301851 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001852 "gem-port-id": gemPortID,
1853 "intf-id": intfID,
1854 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001855 "device-id": f.deviceHandler.device.Id})
1856 f.onuGemInfoLock.RLock()
1857 onugem, ok := f.onuGemInfoMap[onuID]
1858 f.onuGemInfoLock.RUnlock()
1859 if !ok {
1860 logger.Warnw(ctx, "onu gem info already cleared from cache", log.Fields{
1861 "gem-port-id": gemPortID,
1862 "intf-id": intfID,
1863 "onu-id": onuID,
1864 "device-id": f.deviceHandler.device.Id})
1865 return
1866 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001867deleteLoop:
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001868 for j, gem := range onugem.GemPorts {
1869 // If the gemport is found, delete it from local cache.
1870 if gem == gemPortID {
1871 onugem.GemPorts = append(onugem.GemPorts[:j], onugem.GemPorts[j+1:]...)
1872 f.onuGemInfoLock.Lock()
1873 f.onuGemInfoMap[onuID] = onugem
1874 f.onuGemInfoLock.Unlock()
1875 logger.Infow(ctx, "removed-gemport-from-local-cache",
1876 log.Fields{
1877 "intf-id": intfID,
1878 "onu-id": onuID,
1879 "deletedgemport-id": gemPortID,
1880 "gemports": onugem.GemPorts,
1881 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001882 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301883 }
1884 }
1885}
1886
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301887//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001888// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001889func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Girish Gowdra82c80982021-03-26 16:22:02 -07001890 gemPortID int32, flowID uint64, portNum uint32, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001891
Girish Gowdraa482f272021-03-24 23:04:19 -07001892 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
1893 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001894 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1895 log.Fields{
1896 "tpPath": tpPath,
1897 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001898
1899 used := f.isGemPortUsedByAnotherFlow(uint32(gemPortID))
1900
1901 if used {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001902 f.gemToFlowIDsKey.RLock()
1903 flowIDs := f.gemToFlowIDs[uint32(gemPortID)]
1904 f.gemToFlowIDsKey.RUnlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001905
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001906 for i, flowIDinMap := range flowIDs {
1907 if flowIDinMap == flowID {
1908 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001909 f.gemToFlowIDsKey.Lock()
1910 f.gemToFlowIDs[uint32(gemPortID)] = flowIDs
1911 f.gemToFlowIDsKey.Unlock()
1912 // everytime gemToFlowIDs cache is updated the same should be updated
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001913 // in kv store by calling UpdateFlowIDsForGem
Girish Gowdraa482f272021-03-24 23:04:19 -07001914 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, intfID, uint32(gemPortID), flowIDs); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001915 return err
1916 }
1917 break
1918 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001919 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001920 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1921 log.Fields{
1922 "gemport-id": gemPortID,
1923 "usedByFlows": flowIDs,
1924 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -07001925
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001926 return nil
1927 }
1928 logger.Debugf(ctx, "gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
Girish Gowdraa482f272021-03-24 23:04:19 -07001929 f.deleteGemPortFromLocalCache(ctx, intfID, uint32(onuID), uint32(gemPortID))
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001930 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, intfID, uint32(onuID), uint32(gemPortID)) // ignore error and proceed.
1931 //everytime an entry is deleted from gemToFlowIDs cache, the same should be updated in kv as well
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001932 // by calling DeleteFlowIDsForGem
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001933 f.gemToFlowIDsKey.Lock()
1934 delete(f.gemToFlowIDs, uint32(gemPortID))
1935 f.gemToFlowIDsKey.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001936
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001937 f.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, uint32(gemPortID))
1938
1939 f.resourceMgr.FreeGemPortID(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001940
Mahir Gunyel1d20eff2021-07-04 15:39:36 -07001941 //First remove TCONT from child if needed. Then remove the GEM.
1942 //It is expected from child to clean ani side conf if all GEMs of TP are deleted.
1943 //Before this, ensure that the related TCONT deletions are informed to child.
1944 //Refer to VOL-4215.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001945 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1946 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1947 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1948 log.Fields{
1949 "tp-id": tpID,
1950 "path": tpPath}, err)
1951 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001952 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001953 case *tp_pb.TechProfileInstance:
Gamze Abakacb0e6772021-06-10 08:32:12 +00001954 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst, uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001955 if !ok {
Girish Gowdraa482f272021-03-24 23:04:19 -07001956 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001957 logger.Warn(ctx, err)
1958 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001959 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001960 logger.Warn(ctx, err)
1961 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001962 if err := f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001963 logger.Warn(ctx, err)
1964 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001965 if err := f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001966 logger.Warn(ctx, err)
1967 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001968 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001969 case *tp_pb.EponTechProfileInstance:
Girish Gowdraa482f272021-03-24 23:04:19 -07001970 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001971 logger.Warn(ctx, err)
1972 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001973 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001974 logger.Warn(ctx, err)
1975 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001976 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001977 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001978 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001979 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05301980 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07001981 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05301982 "onu-id": onuID,
1983 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001984 "device-id": f.deviceHandler.device.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001985 "alloc-id": techprofileInst.AllocId})
Gamze Abakafee36392019-10-03 11:17:24 +00001986 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001987 default:
1988 logger.Errorw(ctx, "error-unknown-tech",
1989 log.Fields{
1990 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001991 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001992
Mahir Gunyel1d20eff2021-07-04 15:39:36 -07001993 // Delete the gem port on the ONU. Send Gem Removal After TCONT removal.
1994 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
1995 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
1996 log.Fields{
1997 "err": err,
1998 "intfID": intfID,
1999 "onu-id": onuID,
2000 "uni-id": uniID,
2001 "device-id": f.deviceHandler.device.Id,
2002 "gemport-id": gemPortID})
2003 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302004 return nil
2005}
2006
David K. Bainbridge794735f2020-02-11 21:01:37 -08002007// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002008func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002009 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302010 log.Fields{
2011 "flowDirection": flowDirection,
2012 "flow": *flow,
2013 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002014
2015 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002016 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002017 }
2018
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302019 classifierInfo := make(map[string]interface{})
2020
Neha Sharma96b7bf22020-06-15 10:37:32 +00002021 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302022 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002023 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002024 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302025 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302026
David K. Bainbridge794735f2020-02-11 21:01:37 -08002027 onuID := int32(onu)
2028 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002029 tpID, err := getTpIDFromFlow(ctx, flow)
2030 if err != nil {
2031 return olterrors.NewErrNotFound("tp-id",
2032 log.Fields{
2033 "flow": flow,
2034 "intf-id": Intf,
2035 "onu-id": onuID,
2036 "uni-id": uniID,
2037 "device-id": f.deviceHandler.device.Id}, err)
2038 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302039
2040 for _, field := range flows.GetOfbFields(flow) {
2041 if field.Type == flows.IP_PROTO {
2042 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002043 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302044 }
2045 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002046 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302047 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002048 "flow-id": flow.Id,
2049 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302050 "onu-id": onuID,
2051 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302052
2053 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2054 onuID = -1
2055 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002056 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
2057 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002058 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002059 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002060 log.Fields{
2061 "port-number": inPort,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002062 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002063 return err
David K. Bainbridge794735f2020-02-11 21:01:37 -08002064 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302065 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002066
2067 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
2068 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002069 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2070 return err
2071 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002072
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002073 f.flowIDToGemsLock.Lock()
2074 gems, ok := f.flowIDToGems[flow.Id]
2075 if !ok {
2076 logger.Errorw(ctx, "flow-id-to-gem-map-not-found", log.Fields{"flowID": flow.Id})
2077 f.flowIDToGemsLock.Unlock()
2078 return olterrors.NewErrNotFound("flow-id-to-gem-map-not-found", log.Fields{"flowID": flow.Id}, nil)
2079 }
2080 copyOfGems := make([]uint32, len(gems))
2081 _ = copy(copyOfGems, gems)
2082 // Delete the flow-id to gemport list entry from the map now the flow is deleted.
2083 delete(f.flowIDToGems, flow.Id)
2084 f.flowIDToGemsLock.Unlock()
2085
2086 logger.Debugw(ctx, "gems-to-be-cleared", log.Fields{"gems": copyOfGems})
2087 for _, gem := range copyOfGems {
2088 if err = f.clearResources(ctx, Intf, onuID, uniID, int32(gem), flow.Id, portNum, tpID); err != nil {
Girish Gowdra0aca4982021-01-04 12:44:27 -08002089 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002090 "flow-id": flow.Id,
2091 "device-id": f.deviceHandler.device.Id,
2092 "onu-id": onuID,
2093 "intf": Intf,
2094 "gem": gem,
2095 "err": err,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002096 })
2097 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302098 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302099 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002100
Girish Gowdra82c80982021-03-26 16:22:02 -07002101 // Decrement reference count for the meter associated with the given <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
2102 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, Intf, uint32(onuID), uint32(uniID), tpID, false); err != nil {
2103 return err
2104 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002105 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002106}
2107
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002108//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002109func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002110
Matteo Scandolof16389e2021-05-18 00:47:08 +00002111 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302112 var direction string
2113 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002114
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302115 for _, action := range flows.GetActions(flow) {
2116 if action.Type == flows.OUTPUT {
2117 if out := action.GetOutput(); out != nil {
2118 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002119 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302120 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002121 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002122 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002123 }
2124 }
2125 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002126
2127 if flows.HasGroup(flow) {
2128 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002129 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Esin Karamanccb714b2019-11-29 15:02:06 +00002130 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302131 direction = Upstream
2132 } else {
2133 direction = Downstream
2134 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302135
Girish Gowdracefae192020-03-19 18:14:10 -07002136 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002137 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002138
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002139 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002140}
2141
Esin Karamanae41e2b2019-12-17 18:13:13 +00002142//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2143func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2144 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2145 if ethType, ok := classifierInfo[EthType]; ok {
2146 if ethType.(uint32) == IPv4EthType {
2147 if ipProto, ok := classifierInfo[IPProto]; ok {
2148 if ipProto.(uint32) == IgmpProto {
2149 return true
2150 }
2151 }
2152 }
2153 }
2154 }
2155 return false
2156}
2157
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002158// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
2159func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *voltha.OfpFlowStats, addFlow bool, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdrada69ec12021-11-16 15:04:58 -08002160 if f.deviceHandler.getDeviceDeletionInProgressFlag() {
2161 // The device itself is going to be reset as part of deletion. So nothing to be done.
2162 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": f.deviceHandler.device.Id})
2163 return nil
2164 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002165 // Step1 : Fill flowControlBlock
2166 // Step2 : Push the flowControlBlock to ONU channel
2167 // Step3 : Wait on response channel for response
2168 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002169 startTime := time.Now()
2170 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002171 errChan := make(chan error)
2172 flowCb := flowControlBlock{
2173 ctx: ctx,
2174 addFlow: addFlow,
2175 flow: flow,
2176 flowMetadata: flowMetadata,
2177 errChan: &errChan,
2178 }
2179 inPort, outPort := getPorts(flow)
2180 var onuID uint32
2181 if inPort != InvalidPort && outPort != InvalidPort {
2182 _, _, onuID, _ = ExtractAccessFromFlow(inPort, outPort)
2183 }
Girish Gowdrada69ec12021-11-16 15:04:58 -08002184 if f.flowHandlerRoutineActive[onuID] {
2185 // inPort or outPort is InvalidPort for trap-from-nni flows.
2186 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2187 // Send the flowCb on the ONU flow channel
2188 f.incomingFlows[onuID] <- flowCb
2189 // Wait on the channel for flow handlers return value
2190 err := <-errChan
2191 logger.Infow(ctx, "process-flow-received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
2192 return err
2193 }
2194 logger.Errorw(ctx, "flow handler routine not active for onu", log.Fields{"onuID": onuID, "ponPortIdx": f.ponPortIdx})
2195 return fmt.Errorf("flow-handler-routine-not-active-for-onu-%v-pon-%d", onuID, f.ponPortIdx)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002196}
2197
2198// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2199// Each incoming flow is processed in a synchronous manner, i.e., the flow is processed to completion before picking another
Girish Gowdrada69ec12021-11-16 15:04:58 -08002200func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(handlerRoutineIndex int, subscriberFlowChannel chan flowControlBlock, stopHandler chan bool) {
2201 var flowCb flowControlBlock
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002202 for {
Girish Gowdrada69ec12021-11-16 15:04:58 -08002203 select {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002204 // block on the channel to receive an incoming flow
2205 // process the flow completely before proceeding to handle the next flow
Girish Gowdrada69ec12021-11-16 15:04:58 -08002206 case flowCb = <-subscriberFlowChannel:
2207 if flowCb.addFlow {
2208 logger.Info(flowCb.ctx, "adding-flow-start")
2209 startTime := time.Now()
2210 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2211 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2212 // Pass the return value over the return channel
2213 *flowCb.errChan <- err
2214 } else {
2215 logger.Info(flowCb.ctx, "removing-flow-start")
2216 startTime := time.Now()
2217 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2218 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2219 // Pass the return value over the return channel
2220 *flowCb.errChan <- err
2221 }
2222 case <-stopHandler:
2223 f.flowHandlerRoutineActive[handlerRoutineIndex] = false
2224 return
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002225 }
2226 }
2227}
2228
Girish Gowdrada69ec12021-11-16 15:04:58 -08002229// StopAllFlowHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
2230func (f *OpenOltFlowMgr) StopAllFlowHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
2231 for i, v := range f.stopFlowHandlerRoutine {
2232 if f.flowHandlerRoutineActive[i] {
2233 select {
2234 case v <- true:
2235 case <-time.After(time.Second * 5):
2236 logger.Warnw(ctx, "timeout stopping flow handler routine", log.Fields{"onuID": i, "deviceID": f.deviceHandler.device.Id})
2237 }
2238 }
2239 }
2240 wg.Done()
2241 logger.Debugw(ctx, "stopped all flow handler routines", log.Fields{"ponPortIdx": f.ponPortIdx})
2242}
2243
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002244// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302245// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002246func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002247 classifierInfo := make(map[string]interface{})
2248 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002249 var UsMeterID uint32
2250 var DsMeterID uint32
2251
Neha Sharma96b7bf22020-06-15 10:37:32 +00002252 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302253 log.Fields{
2254 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002255 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002256 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002257
Neha Sharma96b7bf22020-06-15 10:37:32 +00002258 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002259 if err != nil {
2260 // Error logging is already done in the called function
2261 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002262 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302263 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002264
Esin Karamanccb714b2019-11-29 15:02:06 +00002265 if flows.HasGroup(flow) {
2266 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002267 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002268 }
2269
manikkaraj k17652a72019-05-06 09:06:36 -04002270 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002271 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002272 if err != nil {
2273 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002274 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002275 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002276
Neha Sharma96b7bf22020-06-15 10:37:32 +00002277 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302278 log.Fields{
2279 "classifierinfo_inport": classifierInfo[InPort],
2280 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002281 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002282
Humera Kouser94d7a842019-08-25 19:04:32 -04002283 if ethType, ok := classifierInfo[EthType]; ok {
2284 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002285 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002286 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002287 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002288 if ethType.(uint32) == PPPoEDEthType {
2289 if voltha.Port_ETHERNET_NNI == IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
2290 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2291 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2292 }
2293 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002294 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002295 if ipProto, ok := classifierInfo[IPProto]; ok {
2296 if ipProto.(uint32) == IPProtoDhcp {
2297 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302298 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002299 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002300 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002301 }
2302 }
2303 }
2304 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002305 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002306 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002307 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002308 }
A R Karthick1f85b802019-10-11 05:06:05 +00002309
npujarec5762e2020-01-01 14:08:48 +05302310 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002311 // also update flowmgr cache
2312 f.onuGemInfoLock.Lock()
2313 onugem, ok := f.onuGemInfoMap[onuID]
2314 if ok {
2315 found := false
2316 for _, uni := range onugem.UniPorts {
2317 if uni == portNo {
2318 found = true
2319 break
2320 }
2321 }
2322 if !found {
2323 onugem.UniPorts = append(onugem.UniPorts, portNo)
2324 f.onuGemInfoMap[onuID] = onugem
2325 logger.Infow(ctx, "added uni port to onugem cache", log.Fields{"uni": portNo})
2326 }
2327 }
2328 f.onuGemInfoLock.Unlock()
A R Karthick1f85b802019-10-11 05:06:05 +00002329
Neha Sharma96b7bf22020-06-15 10:37:32 +00002330 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002331 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302332 return olterrors.NewErrNotFound("tpid-for-flow",
2333 log.Fields{
2334 "flow": flow,
2335 "intf-id": IntfID,
2336 "onu-id": onuID,
2337 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002338 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002339 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302340 log.Fields{
2341 "tp-id": TpID,
2342 "intf-id": intfID,
2343 "onu-id": onuID,
2344 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002345 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002346 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002347 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002348 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002349 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002350 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002351
2352 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002353 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002354}
Girish Gowdra3d633032019-12-10 16:37:05 +05302355
Esin Karamanccb714b2019-11-29 15:02:06 +00002356// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002357func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002358 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002359 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302360 "classifier-info": classifierInfo,
2361 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002362
Esin Karaman65409d82020-03-18 10:58:18 +00002363 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002364 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002365 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002366 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002367
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002368 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002369
David K. Bainbridge794735f2020-02-11 21:01:37 -08002370 onuID := NoneOnuID
2371 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002372
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002373 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002374 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002375 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002376 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002377 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2378 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002379 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002380 }
2381 groupID := actionInfo[GroupID].(uint32)
2382 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002383 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002384 FlowType: Multicast,
2385 NetworkIntfId: int32(networkInterfaceID),
2386 GroupId: groupID,
2387 Classifier: classifierProto,
2388 Priority: int32(flow.Priority),
2389 Cookie: flow.Cookie}
2390
Kent Hagermane6ff1012020-07-14 15:07:53 -04002391 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002392 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002393 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002394 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002395 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002396 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002397 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002398 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002399 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002400 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002401 //cached group can be removed now
2402 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002403 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002404 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002405 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002406
David K. Bainbridge794735f2020-02-11 21:01:37 -08002407 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002408}
2409
Esin Karaman65409d82020-03-18 10:58:18 +00002410//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2411func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2412 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002413 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002414 if err != nil {
2415 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2416 }
2417 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002418 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002419
2420 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2421 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002422}
2423
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002424//sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002425func (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 -07002426
Neha Sharma96b7bf22020-06-15 10:37:32 +00002427 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302428 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002429 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302430 log.Fields{
2431 "intf-id": intfID,
2432 "onu-id": onuID,
2433 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002434 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302435 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002436 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002437
Neha Sharma96b7bf22020-06-15 10:37:32 +00002438 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002439 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{
2440 UniId: uniID,
2441 TpInstancePath: tpPath,
2442 TechTpInstance: &ic.InterAdapterTechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
2443 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002444 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002445 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
manikkaraj k17652a72019-05-06 09:06:36 -04002446 tpDownloadMsg,
2447 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03002448 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002449 onuDev.deviceType,
2450 onuDev.deviceID,
2451 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002452 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302453 return olterrors.NewErrCommunication("send-techprofile-download-request",
2454 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03002455 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05302456 "to-adapter": onuDev.deviceType,
2457 "onu-id": onuDev.deviceID,
2458 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002459 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002460 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302461 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302462}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002463
Girish Gowdra37f13fa2021-08-16 10:59:45 -07002464//AddOnuInfoToFlowMgrCacheAndKvStore function adds onu info to cache and kvstore
2465func (f *OpenOltFlowMgr) AddOnuInfoToFlowMgrCacheAndKvStore(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302466
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002467 f.onuGemInfoLock.RLock()
2468 _, ok := f.onuGemInfoMap[onuID]
2469 f.onuGemInfoLock.RUnlock()
Girish Gowdra9602eb42020-09-09 15:50:39 -07002470 // If the ONU already exists in onuGemInfo list, nothing to do
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002471 if ok {
2472 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2473 log.Fields{"onuID": onuID,
2474 "serialNum": serialNum})
2475 return nil
Girish Gowdra9602eb42020-09-09 15:50:39 -07002476 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002477
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002478 onuGemInfo := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2479 f.onuGemInfoLock.Lock()
2480 f.onuGemInfoMap[onuID] = &onuGemInfo
2481 f.onuGemInfoLock.Unlock()
2482 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onuID, onuGemInfo); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002483 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302484 }
Girish Gowdra37f13fa2021-08-16 10:59:45 -07002485 logger.Infow(ctx, "added-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302486 log.Fields{
2487 "intf-id": intfID,
2488 "onu-id": onuID,
2489 "serial-num": serialNum,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002490 "onu": onuGemInfo,
Shrey Baid26912972020-04-16 21:02:31 +05302491 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002492 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002493}
2494
Girish Gowdra37f13fa2021-08-16 10:59:45 -07002495//RemoveOnuInfoFromFlowMgrCacheAndKvStore function adds onu info to cache and kvstore
2496func (f *OpenOltFlowMgr) RemoveOnuInfoFromFlowMgrCacheAndKvStore(ctx context.Context, intfID uint32, onuID uint32) error {
2497
2498 f.onuGemInfoLock.Lock()
2499 delete(f.onuGemInfoMap, onuID)
2500 f.onuGemInfoLock.Unlock()
2501
2502 if err := f.resourceMgr.DelOnuGemInfo(ctx, intfID, onuID); err != nil {
2503 return err
2504 }
2505 logger.Infow(ctx, "deleted-onuinfo",
2506 log.Fields{
2507 "intf-id": intfID,
2508 "onu-id": onuID,
2509 "device-id": f.deviceHandler.device.Id})
2510 return nil
2511}
2512
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302513//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302514func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002515
Neha Sharma96b7bf22020-06-15 10:37:32 +00002516 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302517 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002518 "gem-port-id": gemPort,
2519 "intf-id": intfID,
2520 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002521 "device-id": f.deviceHandler.device.Id})
2522 f.onuGemInfoLock.RLock()
2523 onugem, ok := f.onuGemInfoMap[onuID]
2524 f.onuGemInfoLock.RUnlock()
2525 if !ok {
2526 logger.Warnw(ctx, "onu gem info is missing", log.Fields{
2527 "gem-port-id": gemPort,
2528 "intf-id": intfID,
2529 "onu-id": onuID,
2530 "device-id": f.deviceHandler.device.Id})
2531 return
2532 }
2533
2534 if onugem.OnuID == onuID {
2535 // check if gem already exists , else update the cache and kvstore
2536 for _, gem := range onugem.GemPorts {
2537 if gem == gemPort {
2538 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
2539 log.Fields{
2540 "gem": gemPort,
2541 "device-id": f.deviceHandler.device.Id})
2542 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302543 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302544 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002545 onugem.GemPorts = append(onugem.GemPorts, gemPort)
2546 f.onuGemInfoLock.Lock()
2547 f.onuGemInfoMap[onuID] = onugem
2548 f.onuGemInfoLock.Unlock()
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002549 logger.Debugw(ctx, "updated onu gem info from cache", log.Fields{"onugem": onugem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002550 } else {
2551 logger.Warnw(ctx, "mismatched onu id", log.Fields{
2552 "gem-port-id": gemPort,
2553 "intf-id": intfID,
2554 "onu-id": onuID,
2555 "device-id": f.deviceHandler.device.Id})
2556 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302557 }
npujarec5762e2020-01-01 14:08:48 +05302558 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302559 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002560 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302561 log.Fields{
2562 "intf-id": intfID,
2563 "onu-id": onuID,
2564 "gemPort": gemPort,
2565 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002566 return
2567 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002568 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302569 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002570 "gem-port-id": gemPort,
2571 "intf-id": intfID,
2572 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002573 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002574}
2575
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002576//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302577func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002578 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002579
2580 if packetIn.IntfType == "pon" {
2581 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002582 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002583 onuID, uniID := packetIn.OnuId, packetIn.UniId
2584 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 +00002585
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002586 if packetIn.PortNo != 0 {
2587 logicalPortNum = packetIn.PortNo
2588 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002589 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002590 }
2591 // 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 +00002592 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002593 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002594 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002595 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002596
2597 if logger.V(log.DebugLevel) {
2598 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2599 log.Fields{
2600 "logical-port-num": logicalPortNum,
2601 "intf-type": packetIn.IntfType,
2602 "packet": hex.EncodeToString(packetIn.Pkt),
2603 })
2604 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002605 return logicalPortNum, nil
2606}
2607
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002608//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002609func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002610 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002611
2612 ctag, priority, err := getCTagFromPacket(ctx, packet)
2613 if err != nil {
2614 return 0, err
2615 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302616
Esin Karaman7fb80c22020-07-16 14:23:33 +00002617 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002618 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002619 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002620 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002621 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302622 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002623 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302624 log.Fields{
2625 "pktinkey": pktInkey,
2626 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002627
2628 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002629 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302630 //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 +00002631 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302632 if err == nil {
2633 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002634 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302635 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002636 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002637 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302638 log.Fields{
2639 "pktinkey": pktInkey,
2640 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302641 return gemPortID, nil
2642 }
2643 }
Shrey Baid26912972020-04-16 21:02:31 +05302644 return uint32(0), olterrors.NewErrNotFound("gem-port",
2645 log.Fields{
2646 "pktinkey": pktInkey,
2647 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002648
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002649}
2650
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002651func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2652 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002653 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002654 classifier[PacketTagType] = DoubleTag
2655 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002656 /* We manage flowId resource pool on per PON port basis.
2657 Since this situation is tricky, as a hack, we pass the NNI port
2658 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002659 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002660 on NNI port, use onu_id as -1 (invalid)
2661 ****************** CAVEAT *******************
2662 This logic works if the NNI Port Id falls within the same valid
2663 range of PON Port Ids. If this doesn't work for some OLT Vendor
2664 we need to have a re-look at this.
2665 *********************************************
2666 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002667 onuID := -1
2668 uniID := -1
2669 gemPortID := -1
2670 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002671 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302672 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302673 return olterrors.NewErrNotFound("nni-intreface-id",
2674 log.Fields{
2675 "classifier": classifier,
2676 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002677 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302678 }
2679
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002680 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002681 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002682 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002683 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002684
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002685 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2686 log.Fields{
2687 "classifier": classifier,
2688 "action": action,
2689 "flowId": logicalFlow.Id,
2690 "intf-id": networkInterfaceID})
2691
David K. Bainbridge794735f2020-02-11 21:01:37 -08002692 classifierProto, err := makeOpenOltClassifierField(classifier)
2693 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002694 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002695 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002696 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002697 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002698 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002699 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002700 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002701 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002702 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2703 OnuId: int32(onuID), // OnuId not required
2704 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002705 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002706 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002707 AllocId: int32(allocID), // AllocId not used
2708 NetworkIntfId: int32(networkInterfaceID),
2709 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002710 Classifier: classifierProto,
2711 Action: actionProto,
2712 Priority: int32(logicalFlow.Priority),
2713 Cookie: logicalFlow.Cookie,
2714 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002715 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002716 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002717 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002718 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002719 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002720}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002721
Esin Karamanae41e2b2019-12-17 18:13:13 +00002722//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2723func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2724 var packetType string
2725 ovid, ivid := false, false
2726 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2727 vid := vlanID & VlanvIDMask
2728 if vid != ReservedVlan {
2729 ovid = true
2730 }
2731 }
2732 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2733 vid := uint32(metadata)
2734 if vid != ReservedVlan {
2735 ivid = true
2736 }
2737 }
2738 if ovid && ivid {
2739 packetType = DoubleTag
2740 } else if !ovid && !ivid {
2741 packetType = Untagged
2742 } else {
2743 packetType = SingleTag
2744 }
2745 return packetType
2746}
2747
2748//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002749func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002750 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002751 action := make(map[string]interface{})
2752 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2753 action[TrapToHost] = true
2754 /* We manage flowId resource pool on per PON port basis.
2755 Since this situation is tricky, as a hack, we pass the NNI port
2756 index (network_intf_id) as PON port Index for the flowId resource
2757 pool. Also, there is no ONU Id available for trapping packets
2758 on NNI port, use onu_id as -1 (invalid)
2759 ****************** CAVEAT *******************
2760 This logic works if the NNI Port Id falls within the same valid
2761 range of PON Port Ids. If this doesn't work for some OLT Vendor
2762 we need to have a re-look at this.
2763 *********************************************
2764 */
2765 onuID := -1
2766 uniID := -1
2767 gemPortID := -1
2768 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002769 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002770 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302771 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002772 "classifier": classifier,
2773 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002774 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002775 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002776 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002777 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002778 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002779 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002780
David K. Bainbridge794735f2020-02-11 21:01:37 -08002781 classifierProto, err := makeOpenOltClassifierField(classifier)
2782 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002783 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002784 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002785 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002786 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002787 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002788 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002789 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002790 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002791 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2792 OnuId: int32(onuID), // OnuId not required
2793 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002794 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002795 FlowType: Downstream,
2796 AllocId: int32(allocID), // AllocId not used
2797 NetworkIntfId: int32(networkInterfaceID),
2798 GemportId: int32(gemPortID), // GemportId not used
2799 Classifier: classifierProto,
2800 Action: actionProto,
2801 Priority: int32(logicalFlow.Priority),
2802 Cookie: logicalFlow.Cookie,
2803 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002804 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002805 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002806 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002807 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002808
David K. Bainbridge794735f2020-02-11 21:01:37 -08002809 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002810}
2811
salmansiddiqui7ac62132019-08-22 03:58:50 +00002812func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2813 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302814 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002815 }
2816 if Dir == tp_pb.Direction_UPSTREAM {
2817 return "upstream", nil
2818 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2819 return "downstream", nil
2820 }
2821 return "", nil
2822}
2823
Kent Hagermane6ff1012020-07-14 15:07:53 -04002824// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302825func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002826 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002827 tpID uint32, uni string) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002828 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002829 intfID := args[IntfID]
2830 onuID := args[OnuID]
2831 uniID := args[UniID]
2832 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002833 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002834 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002835 gemToAes := make(map[uint32]bool)
2836
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002837 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002838 var direction = tp_pb.Direction_UPSTREAM
2839 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002840 case *tp_pb.TechProfileInstance:
Gamze Abaka7650be62021-02-26 10:50:36 +00002841 if IsUpstream(actionInfo[Output].(uint32)) {
2842 attributes = TpInst.UpstreamGemPortAttributeList
2843 } else {
2844 attributes = TpInst.DownstreamGemPortAttributeList
2845 direction = tp_pb.Direction_DOWNSTREAM
2846 }
2847 default:
2848 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
2849 return
2850 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002851
2852 if len(gemPorts) == 1 {
2853 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002854 gemPortID = gemPorts[0]
2855 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002856 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2857 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002858 pBitMap := attributes[idx].PbitMap
2859 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2860 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2861 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
2862 // this pcp bit traffic.
2863 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2864 if pbitSet == pbit1 {
2865 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2866 pbitToGem[pcp] = gemID
2867 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002868 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002869 }
2870 }
2871 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002872 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2873 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2874 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002875 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002876 }
2877
Gamze Abaka7650be62021-02-26 10:50:36 +00002878 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2879 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2880
salmansiddiqui7ac62132019-08-22 03:58:50 +00002881 if ipProto, ok := classifierInfo[IPProto]; ok {
2882 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002883 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002884 "tp-id": tpID,
2885 "alloc-id": allocID,
2886 "intf-id": intfID,
2887 "onu-id": onuID,
2888 "uni-id": uniID,
2889 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002890 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002891 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002892 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002893 }
2894
Girish Gowdra32625212020-04-29 11:26:35 -07002895 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002896 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302897 log.Fields{
2898 "intf-id": intfID,
2899 "onu-id": onuID,
2900 "uni-id": uniID,
2901 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002902 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002903 logger.Warn(ctx, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002904 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002905 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002906 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002907 return
2908 }
2909 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002910 if ethType.(uint32) == EapEthType {
2911 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002912 "intf-id": intfID,
2913 "onu-id": onuID,
2914 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002915 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002916 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002917 var vlanID uint32
2918 if val, ok := classifierInfo[VlanVid]; ok {
2919 vlanID = (val.(uint32)) & VlanvIDMask
2920 } else {
2921 vlanID = DefaultMgmtVlan
2922 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002923 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002924 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002925 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002926 } else if ethType.(uint32) == PPPoEDEthType {
2927 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2928 "tp-id": tpID,
2929 "alloc-id": allocID,
2930 "intf-id": intfID,
2931 "onu-id": onuID,
2932 "uni-id": uniID,
2933 })
2934 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002935 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002936 logger.Warn(ctx, err)
2937 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002938 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002939 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002940 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002941 "intf-id": intfID,
2942 "onu-id": onuID,
2943 "uni-id": uniID,
2944 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002945 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002946 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002947 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002948 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002949 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002950 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002951 "intf-id": intfID,
2952 "onu-id": onuID,
2953 "uni-id": uniID,
2954 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002955 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002956 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002957 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002958 }
2959 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002960 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05302961 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002962 "intf-id": intfID,
2963 "onu-id": onuID,
2964 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05302965 "classifier": classifierInfo,
2966 "action": actionInfo,
2967 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002968 return
2969 }
2970 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002971 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002972 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002973 logger.Warn(ctx, err)
2974 }
2975 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002976}
2977
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002978func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002979 f.gemToFlowIDsKey.RLock()
2980 flowIDList := f.gemToFlowIDs[gemPortID]
2981 f.gemToFlowIDsKey.RUnlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002982 return len(flowIDList) > 1
2983
Gamze Abakafee36392019-10-03 11:17:24 +00002984}
2985
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002986func (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 +05302987 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002988 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2989 for _, currentGemPort := range currentGemPorts {
2990 for _, tpGemPort := range tpGemPorts {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002991 if (currentGemPort == tpGemPort.GemportId) && (currentGemPort != gemPortID) {
Gamze Abakafee36392019-10-03 11:17:24 +00002992 return true, currentGemPort
2993 }
2994 }
2995 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00002996 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
2997 return false, 0
2998}
Girish Gowdra54934262019-11-13 14:19:55 +05302999
Gamze Abakacb0e6772021-06-10 08:32:12 +00003000func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003001 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
3002 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
3003 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 +00003004 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303005 for i := 0; i < len(tpInstances); i++ {
3006 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00003007 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003008 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Gamze Abakacb0e6772021-06-10 08:32:12 +00003009 logger.Debugw(ctx, "alloc-is-in-use",
3010 log.Fields{
3011 "device-id": f.deviceHandler.device.Id,
3012 "intfID": sq.intfID,
3013 "onuID": sq.onuID,
3014 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003015 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00003016 })
3017 return true
Girish Gowdra54934262019-11-13 14:19:55 +05303018 }
3019 }
3020 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00003021 return false
Gamze Abakafee36392019-10-03 11:17:24 +00003022}
3023
Neha Sharma96b7bf22020-06-15 10:37:32 +00003024func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003025 for _, field := range flows.GetOfbFields(flow) {
3026 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003027 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003028 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003029 } else if field.Type == flows.ETH_DST {
3030 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003031 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003032 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003033 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003034 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003035 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003036 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003037 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003038 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05303039 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003040 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003041 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003042 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003043 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003044 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003045 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003046 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003047 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003048 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003049 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003050 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003051 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003052 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003053 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003054 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003055 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003056 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003057 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003058 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003059 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003060 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003061 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003062 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003063 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003064 return
3065 }
3066 }
3067}
3068
Neha Sharma96b7bf22020-06-15 10:37:32 +00003069func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003070 for _, action := range flows.GetActions(flow) {
3071 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003072 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003073 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003074 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003075 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003076 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003077 }
Scott Baker355d1742019-10-24 10:57:52 -07003078 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003079 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003080 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003081 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003082 if out := action.GetPush(); out != nil {
3083 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003084 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003085 } else {
3086 actionInfo[PushVlan] = true
3087 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003088 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303089 log.Fields{
3090 "push-tpid": actionInfo[TPID].(uint32),
3091 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003092 }
3093 }
Scott Baker355d1742019-10-24 10:57:52 -07003094 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003095 if out := action.GetSetField(); out != nil {
3096 if field := out.GetField(); field != nil {
3097 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003098 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003099 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003100 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3101 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003102 }
3103 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003104 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003105 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003106 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003107 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003108 }
3109 }
3110 return nil
3111}
3112
Neha Sharma96b7bf22020-06-15 10:37:32 +00003113func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003114 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003115 fieldtype := ofbField.GetType()
3116 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003117 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3118 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003119 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003120 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003121 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003122 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003123 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3124 pcp := ofbField.GetVlanPcp()
3125 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003126 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003127 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003128 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003129 }
3130 }
3131}
3132
Neha Sharma96b7bf22020-06-15 10:37:32 +00003133func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003134 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003135 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003136 } else {
3137 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003138 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003139 }
3140}
3141
Neha Sharma96b7bf22020-06-15 10:37:32 +00003142func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003143 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003144 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003145 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3146 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003147 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003148 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003149 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303150 log.Fields{
3151 "newinport": classifierInfo[InPort].(uint32),
3152 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003153 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303154 return olterrors.NewErrNotFound("child-in-port",
3155 log.Fields{
3156 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3157 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003158 }
3159 }
3160 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003161 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003162 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003163 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003164 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003165 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003166 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303167 log.Fields{
3168 "newoutport": actionInfo[Output].(uint32),
3169 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003170 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303171 return olterrors.NewErrNotFound("out-port",
3172 log.Fields{
3173 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3174 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003175 }
3176 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3177 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003178 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003179 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003180 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303181 log.Fields{
3182 "newinport": actionInfo[Output].(uint32),
3183 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003184 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303185 return olterrors.NewErrNotFound("nni-port",
3186 log.Fields{
3187 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3188 "in-port": classifierInfo[InPort].(uint32),
3189 "out-port": actionInfo[Output].(uint32),
3190 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003191 }
3192 }
3193 }
3194 return nil
3195}
Gamze Abakafee36392019-10-03 11:17:24 +00003196
Neha Sharma96b7bf22020-06-15 10:37:32 +00003197func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003198 /* Metadata 8 bytes:
3199 Most Significant 2 Bytes = Inner VLAN
3200 Next 2 Bytes = Tech Profile ID(TPID)
3201 Least Significant 4 Bytes = Port ID
3202 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3203 subscriber related flows.
3204 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003205 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003206 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003207 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003208 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003209 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003210 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003211}
3212
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003213func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3214 for _, sliceElement := range slice {
3215 if sliceElement == item {
3216 return slice
3217 }
3218 }
3219 return append(slice, item)
3220}
3221
3222func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003223 for _, sliceElement := range slice {
3224 if sliceElement == item {
3225 return slice
3226 }
3227 }
3228 return append(slice, item)
3229}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303230
3231// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003232func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303233
3234 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3235 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003236 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003237 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003238 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003239 log.Fields{
3240 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003241 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003242 return uint32(0), err
3243 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003244 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303245 return intfID, nil
3246 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003247 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003248 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003249 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003250 log.Fields{
3251 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003252 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003253 return uint32(0), err
3254 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003255 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303256 return intfID, nil
3257 }
3258 return uint32(0), nil
3259}
3260
3261// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003262func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3263 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3264 if err != nil {
3265 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3266 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3267 return
3268 }
3269 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003270
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003271 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003272 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003273 f.packetInGemPortLock.RUnlock()
3274
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303275 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003276 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003277 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 +05303278 log.Fields{
3279 "pktinkey": pktInkey,
3280 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003281 return
3282 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303283 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003284 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003285 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003286 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003287
npujarec5762e2020-01-01 14:08:48 +05303288 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003289 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 +05303290 log.Fields{
3291 "pktinkey": pktInkey,
3292 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303293}
3294
Esin Karaman7fb80c22020-07-16 14:23:33 +00003295//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3296func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3297 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003298 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003299 return 0, 0, errors.New("invalid packet length")
3300 }
3301 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3302 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3303
3304 var index int8
3305 if outerEthType == 0x8100 {
3306 if innerEthType == 0x8100 {
3307 // q-in-q 802.1ad or 802.1q double tagged packet.
3308 // get the inner vlanId
3309 index = 18
3310 } else {
3311 index = 14
3312 }
3313 priority := (packet[index] >> 5) & 0x7
3314 //13 bits composes vlanId value
3315 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3316 return vlan, priority, nil
3317 }
3318 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3319 return 0, 0, nil
3320}
3321
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003322func (f *OpenOltFlowMgr) loadFlowIDsForGemAndGemIDsForFlow(ctx context.Context) {
3323 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - start")
3324 f.onuGemInfoLock.RLock()
3325 f.gemToFlowIDsKey.Lock()
3326 f.flowIDToGemsLock.Lock()
3327 for _, og := range f.onuGemInfoMap {
3328 for _, gem := range og.GemPorts {
3329 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, f.ponPortIdx, gem)
Gamze Abaka3e268512021-09-08 01:14:33 +00003330 if err == nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003331 f.gemToFlowIDs[gem] = flowIDs
3332 for _, flowID := range flowIDs {
3333 if _, ok := f.flowIDToGems[flowID]; !ok {
3334 f.flowIDToGems[flowID] = []uint32{gem}
3335 } else {
3336 f.flowIDToGems[flowID] = appendUnique32bit(f.flowIDToGems[flowID], gem)
3337 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303338 }
3339 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303340 }
3341 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003342 f.flowIDToGemsLock.Unlock()
3343 f.gemToFlowIDsKey.Unlock()
3344 f.onuGemInfoLock.RUnlock()
3345 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - end")
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303346}
Esin Karamanccb714b2019-11-29 15:02:06 +00003347
Girish Gowdra9602eb42020-09-09 15:50:39 -07003348//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3349// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003350func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003351 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003352 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3353 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003354 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003355 "flow-id": flow.Id,
3356 "device-id": f.deviceHandler.device.Id})
3357 // Remove from device
3358 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3359 // DKB
3360 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3361 log.Fields{
3362 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003363 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003364 return err
3365 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003366
3367 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003368}
3369
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003370func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, ponID uint32, onuID uint32, uniID uint32) *ic.InterAdapterTechProfileDownloadMessage {
3371 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003372 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003373 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
3374 return nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003375 }
3376
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003377 switch tpInst := tpInst.(type) {
3378 case *tp_pb.TechProfileInstance:
3379 logger.Debugw(ctx, "fetched-tp-instance-successfully--formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
3380 return &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID,
3381 TpInstancePath: tpPath,
3382 TechTpInstance: &ic.InterAdapterTechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003383 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003384 case *openoltpb2.EponTechProfileInstance:
3385 return &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID,
3386 TpInstancePath: tpPath,
3387 TechTpInstance: &ic.InterAdapterTechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
3388 }
3389 default:
3390 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003391 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003392 return nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003393}
3394
Girish Gowdrabcf98af2021-07-01 08:24:42 -07003395func (f *OpenOltFlowMgr) getOnuGemInfoList(ctx context.Context) []rsrcMgr.OnuGemInfo {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003396 var onuGemInfoLst []rsrcMgr.OnuGemInfo
3397 f.onuGemInfoLock.RLock()
3398 defer f.onuGemInfoLock.RUnlock()
3399 for _, v := range f.onuGemInfoMap {
3400 onuGemInfoLst = append(onuGemInfoLst, *v)
3401 }
3402 return onuGemInfoLst
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003403}