blob: 119ec958a1fb9bed22261630443eaa921797148c [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 {
Andrea Campanella8f645562021-10-28 11:50:56 +0530975 flowContext.classifier[PacketTagType] = SingleTag // FIXME: This hardcoding needs to be removed.
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
Andrea Campanella8f645562021-10-28 11:50:56 +0530988 // TODO: For now mark the PacketTagType as SingleTag when OLT is transparent to VLAN
989 // Per some deployment models, it is also possible that ONU operates on double tagged packets,
990 // so this hardcoding of SingeTag packet-tag-type may be problem for such deployment models.
991 // Need a better way for detection of packet tag type from OpenFlow message.
992 if _, ok := downlinkClassifier[VlanVid]; !ok {
993 downlinkClassifier[PacketTagType] = SingleTag
994 } else {
995 downlinkClassifier[PacketTagType] = DoubleTag
996 downlinkAction[PopVlan] = true
997 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000998 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530999 log.Fields{
1000 "downlinkClassifier": downlinkClassifier,
1001 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001002 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
1003 if vlan, exists := downlinkClassifier[VlanVid]; exists {
1004 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -07001005 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Gamze Abaka7650be62021-02-26 10:50:36 +00001006 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, flowContext.intfID, flowContext.onuID, flowContext.uniID) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001007 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301008 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +00001009 "flow": flowContext.logicalFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301010 "device-id": f.deviceHandler.device.Id,
Gamze Abaka7650be62021-02-26 10:50:36 +00001011 "onu-id": flowContext.onuID,
1012 "intf-id": flowContext.intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001013 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -04001014 }
1015 }
1016 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301017 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001018
Matt Jeannereted16b7c2019-11-01 13:31:35 -04001019 // vlan_vid is a uint32. must be type asserted as such or conversion fails
1020 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +05301021 if ok {
1022 downlinkAction[VlanVid] = dlClVid & 0xfff
Girish Gowdra26f344b2019-10-23 14:39:13 +05301023 }
1024
Gamze Abaka7650be62021-02-26 10:50:36 +00001025 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301026}
1027
Gamze Abaka7650be62021-02-26 10:50:36 +00001028func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001029
Gamze Abaka7650be62021-02-26 10:50:36 +00001030 intfID := flowContext.intfID
1031 onuID := flowContext.onuID
1032 uniID := flowContext.uniID
1033 classifier := flowContext.classifier
1034 action := flowContext.action
1035 allocID := flowContext.allocID
1036 gemPortID := flowContext.gemPortID
1037 tpID := flowContext.tpID
1038 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001039 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301040 log.Fields{
1041 "intf-id": intfID,
1042 "onu-id": onuID,
1043 "uni-id": uniID,
1044 "device-id": f.deviceHandler.device.Id,
1045 "classifier": classifier,
1046 "action": action,
1047 "direction": direction,
1048 "alloc-id": allocID,
1049 "gemport-id": gemPortID,
1050 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001051
1052 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001053 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301054 log.Fields{
1055 "device-id": f.deviceHandler.device.Id,
1056 "intf-id": intfID,
1057 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001058 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301059 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001060 classifierProto, err := makeOpenOltClassifierField(classifier)
1061 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301062 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301063 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001064 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301065 log.Fields{
1066 "classifier": *classifierProto,
1067 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001068 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001069 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301070 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301071 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001072 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301073 log.Fields{
1074 "action": *actionProto,
1075 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001076 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301077 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301078 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001079 log.Fields{
1080 "classifier": classifier,
1081 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301082 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001083 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301084 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001085
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001086 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001087 OnuId: int32(onuID),
1088 UniId: int32(uniID),
1089 FlowId: logicalFlow.Id,
1090 FlowType: direction,
1091 AllocId: int32(allocID),
1092 NetworkIntfId: int32(networkIntfID),
1093 GemportId: int32(gemPortID),
1094 Classifier: classifierProto,
1095 Action: actionProto,
1096 Priority: int32(logicalFlow.Priority),
1097 Cookie: logicalFlow.Cookie,
1098 PortNo: flowContext.portNo,
1099 TechProfileId: tpID,
1100 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1101 PbitToGemport: flowContext.pbitToGem,
1102 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001103 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001104 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001105 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301106 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001107 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301108 log.Fields{"direction": direction,
1109 "device-id": f.deviceHandler.device.Id,
1110 "flow": flow,
1111 "intf-id": intfID,
1112 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001113
David K. Bainbridge794735f2020-02-11 21:01:37 -08001114 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301115}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001116
Gamze Abaka7650be62021-02-26 10:50:36 +00001117func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1118
1119 intfID := flowContext.intfID
1120 onuID := flowContext.onuID
1121 uniID := flowContext.uniID
1122 logicalFlow := flowContext.logicalFlow
1123 classifier := flowContext.classifier
1124 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301125
Neha Sharma96b7bf22020-06-15 10:37:32 +00001126 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301127 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301128 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001129 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301130 "action": action,
1131 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001132 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301133 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301134
1135 // Clear the action map
1136 for k := range action {
1137 delete(action, k)
1138 }
1139
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001140 action[TrapToHost] = true
1141 classifier[UDPSrc] = uint32(68)
1142 classifier[UDPDst] = uint32(67)
1143 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301144
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001145 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001146 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301147 log.Fields{
1148 "device-id": f.deviceHandler.device.Id,
1149 "intf-id": intfID,
1150 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001151 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301152 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301153
Neha Sharma96b7bf22020-06-15 10:37:32 +00001154 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301155 log.Fields{
1156 "ul_classifier": classifier,
1157 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001158 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301159 "intf-id": intfID,
1160 "onu-id": onuID,
1161 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301162
David K. Bainbridge794735f2020-02-11 21:01:37 -08001163 classifierProto, err := makeOpenOltClassifierField(classifier)
1164 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301165 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301166 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001167 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001168 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001169 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301170 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301171 }
1172
David K. Bainbridge794735f2020-02-11 21:01:37 -08001173 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001174 OnuId: int32(onuID),
1175 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001176 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001177 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001178 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001179 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001180 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301181 Classifier: classifierProto,
1182 Action: actionProto,
1183 Priority: int32(logicalFlow.Priority),
1184 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001185 PortNo: flowContext.portNo,
1186 TechProfileId: flowContext.tpID,
1187 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1188 PbitToGemport: flowContext.pbitToGem,
1189 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001190 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001191 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001192 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001193 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001194 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301195 log.Fields{
1196 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001197 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301198 "intf-id": intfID,
1199 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301200
David K. Bainbridge794735f2020-02-11 21:01:37 -08001201 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301202}
1203
Esin Karamanae41e2b2019-12-17 18:13:13 +00001204//addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001205func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1206 delete(flowContext.classifier, VlanVid)
1207 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001208}
1209
1210//addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001211func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1212
1213 intfID := flowContext.intfID
1214 onuID := flowContext.onuID
1215 uniID := flowContext.uniID
1216 logicalFlow := flowContext.logicalFlow
1217 classifier := flowContext.classifier
1218 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001219
Neha Sharma96b7bf22020-06-15 10:37:32 +00001220 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001221 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301222 return olterrors.NewErrNotFound("nni-interface-id",
1223 log.Fields{
1224 "classifier": classifier,
1225 "action": action,
1226 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001227 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001228 }
1229
1230 // Clear the action map
1231 for k := range action {
1232 delete(action, k)
1233 }
1234
1235 action[TrapToHost] = true
1236 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001237
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001238 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001239 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001240 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001241 }
1242
Neha Sharma96b7bf22020-06-15 10:37:32 +00001243 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301244 log.Fields{
1245 "ul_classifier": classifier,
1246 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001247 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301248 "device-id": f.deviceHandler.device.Id,
1249 "intf-id": intfID,
1250 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001251
David K. Bainbridge794735f2020-02-11 21:01:37 -08001252 classifierProto, err := makeOpenOltClassifierField(classifier)
1253 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301254 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001255 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001256 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301257 log.Fields{
1258 "classifier": *classifierProto,
1259 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001260 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001261 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301262 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001263 }
1264
David K. Bainbridge794735f2020-02-11 21:01:37 -08001265 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001266 OnuId: int32(onuID),
1267 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001268 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001269 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001270 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001271 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001272 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001273 Classifier: classifierProto,
1274 Action: actionProto,
1275 Priority: int32(logicalFlow.Priority),
1276 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001277 PortNo: flowContext.portNo,
1278 TechProfileId: flowContext.tpID,
1279 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1280 PbitToGemport: flowContext.pbitToGem,
1281 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001282 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001283
David K. Bainbridge794735f2020-02-11 21:01:37 -08001284 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001285 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 -08001286 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001287
David K. Bainbridge794735f2020-02-11 21:01:37 -08001288 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001289}
1290
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001291// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001292func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1293 intfID := flowContext.intfID
1294 onuID := flowContext.onuID
1295 uniID := flowContext.uniID
1296 portNo := flowContext.portNo
1297 allocID := flowContext.allocID
1298 gemPortID := flowContext.gemPortID
1299 logicalFlow := flowContext.logicalFlow
1300 classifier := flowContext.classifier
1301 action := flowContext.action
1302
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001303 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301304 log.Fields{
1305 "intf-id": intfID,
1306 "onu-id": onuID,
1307 "port-no": portNo,
1308 "alloc-id": allocID,
1309 "gemport-id": gemPortID,
1310 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001311 "flow": logicalFlow,
1312 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301313
1314 uplinkClassifier := make(map[string]interface{})
1315 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301316
manikkaraj kbf256be2019-03-25 00:13:48 +05301317 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001318 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001319 uplinkClassifier[PacketTagType] = SingleTag
1320 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001321 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301322 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001323 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001324 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001325 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301326 "device-id": f.deviceHandler.device.Id,
1327 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001328 "intf-id": intfID,
1329 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001330 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301331 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001332 //Add Uplink EthType Flow
1333 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301334 log.Fields{
1335 "ul_classifier": uplinkClassifier,
1336 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001337 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301338 "device-id": f.deviceHandler.device.Id,
1339 "intf-id": intfID,
1340 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301341
David K. Bainbridge794735f2020-02-11 21:01:37 -08001342 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1343 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301344 return olterrors.NewErrInvalidValue(log.Fields{
1345 "classifier": uplinkClassifier,
1346 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301347 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001348 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301349 log.Fields{
1350 "classifier": *classifierProto,
1351 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001352 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001353 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301354 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301355 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001356 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301357 log.Fields{
1358 "action": *actionProto,
1359 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001360 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301361 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301362 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001363 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301364 "action": action,
1365 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001366 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301367 }
1368
David K. Bainbridge794735f2020-02-11 21:01:37 -08001369 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001370 OnuId: int32(onuID),
1371 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001372 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001373 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001374 AllocId: int32(allocID),
1375 NetworkIntfId: int32(networkIntfID),
1376 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301377 Classifier: classifierProto,
1378 Action: actionProto,
1379 Priority: int32(logicalFlow.Priority),
1380 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001381 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001382 TechProfileId: flowContext.tpID,
1383 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1384 PbitToGemport: flowContext.pbitToGem,
1385 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001386 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001387 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001388 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001389 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001390 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301391 log.Fields{
1392 "device-id": f.deviceHandler.device.Id,
1393 "onu-id": onuID,
1394 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001395 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301396 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001397
David K. Bainbridge794735f2020-02-11 21:01:37 -08001398 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301399}
1400
David K. Bainbridge794735f2020-02-11 21:01:37 -08001401func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001402 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001403
1404 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1405 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1406 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001407 if vlanID != ReservedVlan {
1408 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001409 classifier.OVid = vid
1410 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301411 }
Andrea Campanella8f645562021-10-28 11:50:56 +05301412 // The classifierInfo[Metadata] carries the vlan that the OLT see when it receives packet from the ONU
David K. Bainbridge82efc492019-09-04 09:57:11 -07001413 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1414 vid := uint32(metadata)
Andrea Campanella8f645562021-10-28 11:50:56 +05301415 // Set the OVid or IVid classifier based on the whether OLT is using a transparent tag or not
1416 // If OLT is using transparent tag mechanism, then it classifies whatever tag it sees to/from ONU which
1417 //is OVid from the perspective of the OLT. When OLT also places or pops the outer tag, then classifierInfo[Metadata]
1418 // becomes the IVid.
1419 if classifier.OVid != 0 && classifier.OVid != ReservedVlan { // This is case when classifier.OVid is not set
1420 if vid != ReservedVlan {
1421 classifier.IVid = vid
1422 }
1423 } else {
1424 if vid != ReservedVlan {
1425 classifier.OVid = vid
1426 }
Harsh Awasthiea45af72019-08-26 02:39:00 -04001427 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301428 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301429 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001430 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301431 classifier.OPbits = vlanPcp
1432 } else {
1433 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301434 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001435 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1436 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1437 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1438 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001439 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001440 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1441 classifier.PktTagType = pktTagType
1442
1443 switch pktTagType {
1444 case SingleTag:
1445 case DoubleTag:
1446 case Untagged:
1447 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001448 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301449 }
1450 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001451 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301452}
1453
Gamze Abaka724d0852020-03-18 12:10:24 +00001454func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001455 var actionCmd openoltpb2.ActionCmd
1456 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301457 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001458 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301459 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001460 if _, ok := actionInfo[VlanPcp]; ok {
1461 action.Cmd.RemarkInnerPbits = true
1462 action.IPbits = actionInfo[VlanPcp].(uint32)
1463 if _, ok := actionInfo[VlanVid]; ok {
1464 action.Cmd.TranslateInnerTag = true
1465 action.IVid = actionInfo[VlanVid].(uint32)
1466 }
1467 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001468 } else if _, ok := actionInfo[PushVlan]; ok {
1469 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301470 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001471 if _, ok := actionInfo[VlanPcp]; ok {
1472 action.OPbits = actionInfo[VlanPcp].(uint32)
1473 action.Cmd.RemarkOuterPbits = true
1474 if _, ok := classifierInfo[VlanVid]; ok {
1475 action.IVid = classifierInfo[VlanVid].(uint32)
1476 action.Cmd.TranslateInnerTag = true
1477 }
1478 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001479 } else if _, ok := actionInfo[TrapToHost]; ok {
1480 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301481 }
Andrea Campanella8f645562021-10-28 11:50:56 +05301482 // When OLT is transparent to vlans no-action is valid.
1483 /*
1484 else {
1485 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
1486 }
1487 */
David K. Bainbridge794735f2020-02-11 21:01:37 -08001488 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301489}
1490
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001491// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001492func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001493 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301494}
1495
Gamze Abakafee36392019-10-03 11:17:24 +00001496// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdra37f13fa2021-08-16 10:59:45 -07001497// We also force release scheduler and queues associated with the tp instance. Theoretically there could be
1498// an issue if the upstream scheduler (DBA) is shared across multiple UNI and we force release it, given that
1499// this function is only meant to clean up TP instances of a given UNI. But in practicality this routine
1500// is only meant to be called when the clean up of resource for the whole ONU is taking place.
1501// The reason for introducing the force cleanup of scheduler and queues (on the OLT) was introduced here
1502// because it was observed that if the ONU device was deleted too soon after the flows were
1503// unprovisioned on that ONU, the scheduler and queue removal pertinent to that ONU would remain
1504// uncleaned on the OLT. So we force clean up here and ignore any error that OLT returns during the
1505// force cleanup (possible if the OLT has already cleared those resources).
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001506func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301507 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001508 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1509
Gamze Abakafee36392019-10-03 11:17:24 +00001510 for _, tpID := range tpIDList {
Girish Gowdra37f13fa2021-08-16 10:59:45 -07001511
1512 // Force cleanup scheduler/queues -- start
1513 uniPortNum := MkUniPortNum(ctx, intfID, onuID, uniID)
1514 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1515 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
1516 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1517 if err != nil || tpInst == nil { // This should not happen, something wrong in KV backend transaction
1518 logger.Warnw(ctx, "tech-profile-not-in-kv-store",
1519 log.Fields{
1520 "tp-id": tpID,
1521 "path": tpPath})
1522 }
1523 switch tpInstance := tpInst.(type) {
1524 case *tp_pb.TechProfileInstance:
1525 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1526 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1527 }
1528 // Force cleanup scheduler/queues -- end
1529
1530 // Now remove the tp instance
npujarec5762e2020-01-01 14:08:48 +05301531 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001532 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301533 // return err
1534 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001535 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001536 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 +00001537 }
1538 return nil
1539}
1540
1541// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301542func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001543 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001544 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001545 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001546 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301547 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1548 log.Fields{
1549 "tp-id": tpID,
1550 "uni-port-name": uniPortName,
1551 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001552 }
1553 return nil
1554}
1555
David K. Bainbridge794735f2020-02-11 21:01:37 -08001556func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001557
1558 var intfID uint32
1559 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1560 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1561 */
1562 if deviceFlow.AccessIntfId != -1 {
1563 intfID = uint32(deviceFlow.AccessIntfId)
1564 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001565 // We need to log the valid interface ID.
1566 // 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 +00001567 intfID = uint32(deviceFlow.NetworkIntfId)
1568 }
1569
Neha Sharma96b7bf22020-06-15 10:37:32 +00001570 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301571 "flow": *deviceFlow,
1572 "device-id": f.deviceHandler.device.Id,
1573 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001574 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001575
1576 st, _ := status.FromError(err)
1577 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001578 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001579 "err": err,
1580 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301581 "device-id": f.deviceHandler.device.Id,
1582 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001583 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301584 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001585
1586 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001587 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301588 log.Fields{"err": err,
1589 "device-flow": deviceFlow,
1590 "device-id": f.deviceHandler.device.Id,
1591 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001592 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001593 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001594 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301595 log.Fields{
1596 "flow": *deviceFlow,
1597 "device-id": f.deviceHandler.device.Id,
1598 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001599
1600 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1601 if deviceFlow.AccessIntfId != -1 {
1602 // No need to register the flow if it is a trap on nni flow.
1603 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1604 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1605 return err
1606 }
1607 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001608 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001609}
1610
Neha Sharma96b7bf22020-06-15 10:37:32 +00001611func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1612 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301613 log.Fields{
1614 "flow": *deviceFlow,
1615 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001616 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001617 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001618 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001619 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301620 log.Fields{
1621 "err": err,
1622 "deviceFlow": deviceFlow,
1623 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001624 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001625 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001626 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001627 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001628
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001629 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001630 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001631 "of-flow-id": ofFlowID,
1632 "flow": *deviceFlow,
1633 "device-id": f.deviceHandler.device.Id,
1634 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001635 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301636}
1637
David K. Bainbridge794735f2020-02-11 21:01:37 -08001638func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001639
1640 classifierInfo := make(map[string]interface{})
1641 actionInfo := make(map[string]interface{})
1642
1643 classifierInfo[EthType] = uint32(LldpEthType)
1644 classifierInfo[PacketTagType] = Untagged
1645 actionInfo[TrapToHost] = true
1646
1647 // LLDP flow is installed to trap LLDP packets on the NNI port.
1648 // We manage flow_id resource pool on per PON port basis.
1649 // Since this situation is tricky, as a hack, we pass the NNI port
1650 // index (network_intf_id) as PON port Index for the flow_id resource
1651 // pool. Also, there is no ONU Id available for trapping LLDP packets
1652 // on NNI port, use onu_id as -1 (invalid)
1653 // ****************** CAVEAT *******************
1654 // This logic works if the NNI Port Id falls within the same valid
1655 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1656 // we need to have a re-look at this.
1657 // *********************************************
1658
1659 var onuID = -1
1660 var uniID = -1
1661 var gemPortID = -1
1662
Neha Sharma96b7bf22020-06-15 10:37:32 +00001663 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001664 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301665 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001666 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001667 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001668 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001669 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001670 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001671
David K. Bainbridge794735f2020-02-11 21:01:37 -08001672 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1673 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301674 return olterrors.NewErrInvalidValue(
1675 log.Fields{
1676 "classifier": classifierInfo,
1677 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001678 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001679 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301680 log.Fields{
1681 "classifier": *classifierProto,
1682 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001683 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001684 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301685 return olterrors.NewErrInvalidValue(
1686 log.Fields{
1687 "action": actionInfo,
1688 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001689 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001690 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301691 log.Fields{
1692 "action": *actionProto,
1693 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001694
1695 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1696 OnuId: int32(onuID), // OnuId not required
1697 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001698 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001699 FlowType: Downstream,
1700 NetworkIntfId: int32(networkInterfaceID),
1701 GemportId: int32(gemPortID),
1702 Classifier: classifierProto,
1703 Action: actionProto,
1704 Priority: int32(flow.Priority),
1705 Cookie: flow.Cookie,
1706 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001707 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001708 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301709 log.Fields{
1710 "flow": downstreamflow,
1711 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001712 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001713 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301714 log.Fields{
1715 "device-id": f.deviceHandler.device.Id,
1716 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001717 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001718
David K. Bainbridge794735f2020-02-11 21:01:37 -08001719 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301720}
1721
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001722func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1723 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001724}
1725
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001726//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001727func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001728 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1729 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1730 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001731 logger.Debugw(ctx, "couldnt-find-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})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001736 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001737 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301738 return nil, olterrors.NewErrNotFound("onu-child-device",
1739 log.Fields{
1740 "onu-id": onuID,
1741 "intf-id": intfID,
1742 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001743 }
1744 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1745 //better to ad the device to cache here.
1746 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1747 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001748 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301749 log.Fields{
1750 "intf-id": intfID,
1751 "onu-id": onuID,
1752 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001753 }
1754
1755 return onuDev.(*OnuDevice), nil
1756}
1757
1758//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001759func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1760 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301761 log.Fields{
1762 "pon-port": intfID,
1763 "onu-id": onuID,
1764 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001765 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001766 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001767 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301768 return nil, olterrors.NewErrNotFound("onu",
1769 log.Fields{
1770 "interface-id": parentPortNo,
1771 "onu-id": onuID,
1772 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001773 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301774 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001775 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301776 log.Fields{
1777 "device-id": f.deviceHandler.device.Id,
1778 "child_device_id": onuDevice.Id,
1779 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301780 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301781}
1782
Neha Sharma96b7bf22020-06-15 10:37:32 +00001783func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1784 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301785 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001786 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301787 log.Fields{
1788 "intf-id": intfID,
1789 "onu-id": onuID,
1790 "uni-id": uniID,
1791 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001792 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301793 }
1794
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001795 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpInstancePath: tpPath, GemPortId: gemPortID}
1796 logger.Infow(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301797 log.Fields{
1798 "msg": *delGemPortMsg,
1799 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001800 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301801 delGemPortMsg,
1802 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001803 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001804 onuDev.deviceType,
1805 onuDev.deviceID,
1806 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301807 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1808 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001809 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301810 "to-adapter": onuDev.deviceType,
1811 "onu-id": onuDev.deviceID,
1812 "proxyDeviceID": onuDev.proxyDeviceID,
1813 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301814 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001815 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301816 log.Fields{
1817 "msg": delGemPortMsg,
1818 "from-adapter": f.deviceHandler.device.Type,
1819 "to-adapter": onuDev.deviceType,
1820 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301821 return nil
1822}
1823
Neha Sharma96b7bf22020-06-15 10:37:32 +00001824func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1825 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301826 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001827 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301828 log.Fields{
1829 "intf-id": intfID,
1830 "onu-id": onuID,
1831 "uni-id": uniID,
1832 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001833 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301834 }
1835
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001836 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpInstancePath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001837 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301838 log.Fields{
1839 "msg": *delTcontMsg,
1840 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001841 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301842 delTcontMsg,
1843 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001844 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001845 onuDev.deviceType,
1846 onuDev.deviceID,
1847 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301848 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1849 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001850 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301851 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1852 "proxyDeviceID": onuDev.proxyDeviceID,
1853 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301854 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001855 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301856 log.Fields{
1857 "msg": delTcontMsg,
1858 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301859 return nil
1860}
1861
Girish Gowdrac3037402020-01-22 20:29:53 +05301862// Once the gemport is released for a given onu, it also has to be cleared from local cache
1863// which was used for deriving the gemport->logicalPortNo during packet-in.
1864// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1865// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001866func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001867 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301868 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001869 "gem-port-id": gemPortID,
1870 "intf-id": intfID,
1871 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001872 "device-id": f.deviceHandler.device.Id})
1873 f.onuGemInfoLock.RLock()
1874 onugem, ok := f.onuGemInfoMap[onuID]
1875 f.onuGemInfoLock.RUnlock()
1876 if !ok {
1877 logger.Warnw(ctx, "onu gem info already cleared from cache", log.Fields{
1878 "gem-port-id": gemPortID,
1879 "intf-id": intfID,
1880 "onu-id": onuID,
1881 "device-id": f.deviceHandler.device.Id})
1882 return
1883 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001884deleteLoop:
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001885 for j, gem := range onugem.GemPorts {
1886 // If the gemport is found, delete it from local cache.
1887 if gem == gemPortID {
1888 onugem.GemPorts = append(onugem.GemPorts[:j], onugem.GemPorts[j+1:]...)
1889 f.onuGemInfoLock.Lock()
1890 f.onuGemInfoMap[onuID] = onugem
1891 f.onuGemInfoLock.Unlock()
1892 logger.Infow(ctx, "removed-gemport-from-local-cache",
1893 log.Fields{
1894 "intf-id": intfID,
1895 "onu-id": onuID,
1896 "deletedgemport-id": gemPortID,
1897 "gemports": onugem.GemPorts,
1898 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001899 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301900 }
1901 }
1902}
1903
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301904//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001905// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001906func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Girish Gowdra82c80982021-03-26 16:22:02 -07001907 gemPortID int32, flowID uint64, portNum uint32, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001908
Girish Gowdraa482f272021-03-24 23:04:19 -07001909 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
1910 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001911 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1912 log.Fields{
1913 "tpPath": tpPath,
1914 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001915
1916 used := f.isGemPortUsedByAnotherFlow(uint32(gemPortID))
1917
1918 if used {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001919 f.gemToFlowIDsKey.RLock()
1920 flowIDs := f.gemToFlowIDs[uint32(gemPortID)]
1921 f.gemToFlowIDsKey.RUnlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001922
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001923 for i, flowIDinMap := range flowIDs {
1924 if flowIDinMap == flowID {
1925 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001926 f.gemToFlowIDsKey.Lock()
1927 f.gemToFlowIDs[uint32(gemPortID)] = flowIDs
1928 f.gemToFlowIDsKey.Unlock()
1929 // everytime gemToFlowIDs cache is updated the same should be updated
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001930 // in kv store by calling UpdateFlowIDsForGem
Girish Gowdraa482f272021-03-24 23:04:19 -07001931 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, intfID, uint32(gemPortID), flowIDs); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001932 return err
1933 }
1934 break
1935 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001936 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001937 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1938 log.Fields{
1939 "gemport-id": gemPortID,
1940 "usedByFlows": flowIDs,
1941 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -07001942
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001943 return nil
1944 }
1945 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 -07001946 f.deleteGemPortFromLocalCache(ctx, intfID, uint32(onuID), uint32(gemPortID))
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001947 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, intfID, uint32(onuID), uint32(gemPortID)) // ignore error and proceed.
1948 //everytime an entry is deleted from gemToFlowIDs cache, the same should be updated in kv as well
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001949 // by calling DeleteFlowIDsForGem
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001950 f.gemToFlowIDsKey.Lock()
1951 delete(f.gemToFlowIDs, uint32(gemPortID))
1952 f.gemToFlowIDsKey.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001953
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001954 f.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, uint32(gemPortID))
1955
1956 f.resourceMgr.FreeGemPortID(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001957
Mahir Gunyel1d20eff2021-07-04 15:39:36 -07001958 //First remove TCONT from child if needed. Then remove the GEM.
1959 //It is expected from child to clean ani side conf if all GEMs of TP are deleted.
1960 //Before this, ensure that the related TCONT deletions are informed to child.
1961 //Refer to VOL-4215.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001962 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1963 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1964 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1965 log.Fields{
1966 "tp-id": tpID,
1967 "path": tpPath}, err)
1968 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001969 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001970 case *tp_pb.TechProfileInstance:
Gamze Abakacb0e6772021-06-10 08:32:12 +00001971 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst, uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001972 if !ok {
Girish Gowdraa482f272021-03-24 23:04:19 -07001973 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001974 logger.Warn(ctx, err)
1975 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001976 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001977 logger.Warn(ctx, err)
1978 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001979 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 -07001980 logger.Warn(ctx, err)
1981 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001982 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 -07001983 logger.Warn(ctx, err)
1984 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001985 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001986 case *tp_pb.EponTechProfileInstance:
Girish Gowdraa482f272021-03-24 23:04:19 -07001987 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001988 logger.Warn(ctx, err)
1989 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001990 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001991 logger.Warn(ctx, err)
1992 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001993 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001994 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001995 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001996 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05301997 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07001998 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05301999 "onu-id": onuID,
2000 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002001 "device-id": f.deviceHandler.device.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002002 "alloc-id": techprofileInst.AllocId})
Gamze Abakafee36392019-10-03 11:17:24 +00002003 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002004 default:
2005 logger.Errorw(ctx, "error-unknown-tech",
2006 log.Fields{
2007 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002008 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002009
Mahir Gunyel1d20eff2021-07-04 15:39:36 -07002010 // Delete the gem port on the ONU. Send Gem Removal After TCONT removal.
2011 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
2012 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
2013 log.Fields{
2014 "err": err,
2015 "intfID": intfID,
2016 "onu-id": onuID,
2017 "uni-id": uniID,
2018 "device-id": f.deviceHandler.device.Id,
2019 "gemport-id": gemPortID})
2020 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302021 return nil
2022}
2023
David K. Bainbridge794735f2020-02-11 21:01:37 -08002024// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002025func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002026 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302027 log.Fields{
2028 "flowDirection": flowDirection,
2029 "flow": *flow,
2030 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002031
2032 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002033 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002034 }
2035
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302036 classifierInfo := make(map[string]interface{})
2037
Neha Sharma96b7bf22020-06-15 10:37:32 +00002038 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302039 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002040 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002041 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302042 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302043
David K. Bainbridge794735f2020-02-11 21:01:37 -08002044 onuID := int32(onu)
2045 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002046 tpID, err := getTpIDFromFlow(ctx, flow)
2047 if err != nil {
2048 return olterrors.NewErrNotFound("tp-id",
2049 log.Fields{
2050 "flow": flow,
2051 "intf-id": Intf,
2052 "onu-id": onuID,
2053 "uni-id": uniID,
2054 "device-id": f.deviceHandler.device.Id}, err)
2055 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302056
2057 for _, field := range flows.GetOfbFields(flow) {
2058 if field.Type == flows.IP_PROTO {
2059 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002060 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302061 }
2062 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002063 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302064 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002065 "flow-id": flow.Id,
2066 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302067 "onu-id": onuID,
2068 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302069
2070 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2071 onuID = -1
2072 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002073 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
2074 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002075 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002076 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002077 log.Fields{
2078 "port-number": inPort,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002079 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002080 return err
David K. Bainbridge794735f2020-02-11 21:01:37 -08002081 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302082 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002083
2084 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
2085 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002086 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2087 return err
2088 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002089
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002090 f.flowIDToGemsLock.Lock()
2091 gems, ok := f.flowIDToGems[flow.Id]
2092 if !ok {
2093 logger.Errorw(ctx, "flow-id-to-gem-map-not-found", log.Fields{"flowID": flow.Id})
2094 f.flowIDToGemsLock.Unlock()
2095 return olterrors.NewErrNotFound("flow-id-to-gem-map-not-found", log.Fields{"flowID": flow.Id}, nil)
2096 }
2097 copyOfGems := make([]uint32, len(gems))
2098 _ = copy(copyOfGems, gems)
2099 // Delete the flow-id to gemport list entry from the map now the flow is deleted.
2100 delete(f.flowIDToGems, flow.Id)
2101 f.flowIDToGemsLock.Unlock()
2102
2103 logger.Debugw(ctx, "gems-to-be-cleared", log.Fields{"gems": copyOfGems})
2104 for _, gem := range copyOfGems {
2105 if err = f.clearResources(ctx, Intf, onuID, uniID, int32(gem), flow.Id, portNum, tpID); err != nil {
Girish Gowdra0aca4982021-01-04 12:44:27 -08002106 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002107 "flow-id": flow.Id,
2108 "device-id": f.deviceHandler.device.Id,
2109 "onu-id": onuID,
2110 "intf": Intf,
2111 "gem": gem,
2112 "err": err,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002113 })
2114 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302115 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302116 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002117
Girish Gowdra82c80982021-03-26 16:22:02 -07002118 // Decrement reference count for the meter associated with the given <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
2119 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, Intf, uint32(onuID), uint32(uniID), tpID, false); err != nil {
2120 return err
2121 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002122 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002123}
2124
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002125//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002126func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002127
Matteo Scandolof16389e2021-05-18 00:47:08 +00002128 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302129 var direction string
2130 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002131
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302132 for _, action := range flows.GetActions(flow) {
2133 if action.Type == flows.OUTPUT {
2134 if out := action.GetOutput(); out != nil {
2135 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002136 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302137 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002138 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002139 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002140 }
2141 }
2142 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002143
2144 if flows.HasGroup(flow) {
2145 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002146 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Esin Karamanccb714b2019-11-29 15:02:06 +00002147 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302148 direction = Upstream
2149 } else {
2150 direction = Downstream
2151 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302152
Girish Gowdracefae192020-03-19 18:14:10 -07002153 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002154 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002155
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002156 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002157}
2158
Esin Karamanae41e2b2019-12-17 18:13:13 +00002159//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2160func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2161 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2162 if ethType, ok := classifierInfo[EthType]; ok {
2163 if ethType.(uint32) == IPv4EthType {
2164 if ipProto, ok := classifierInfo[IPProto]; ok {
2165 if ipProto.(uint32) == IgmpProto {
2166 return true
2167 }
2168 }
2169 }
2170 }
2171 }
2172 return false
2173}
2174
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002175// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
2176func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *voltha.OfpFlowStats, addFlow bool, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdrada69ec12021-11-16 15:04:58 -08002177 if f.deviceHandler.getDeviceDeletionInProgressFlag() {
2178 // The device itself is going to be reset as part of deletion. So nothing to be done.
2179 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": f.deviceHandler.device.Id})
2180 return nil
2181 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002182 // Step1 : Fill flowControlBlock
2183 // Step2 : Push the flowControlBlock to ONU channel
2184 // Step3 : Wait on response channel for response
2185 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002186 startTime := time.Now()
2187 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002188 errChan := make(chan error)
2189 flowCb := flowControlBlock{
2190 ctx: ctx,
2191 addFlow: addFlow,
2192 flow: flow,
2193 flowMetadata: flowMetadata,
2194 errChan: &errChan,
2195 }
2196 inPort, outPort := getPorts(flow)
2197 var onuID uint32
2198 if inPort != InvalidPort && outPort != InvalidPort {
2199 _, _, onuID, _ = ExtractAccessFromFlow(inPort, outPort)
2200 }
Girish Gowdrada69ec12021-11-16 15:04:58 -08002201 if f.flowHandlerRoutineActive[onuID] {
2202 // inPort or outPort is InvalidPort for trap-from-nni flows.
2203 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2204 // Send the flowCb on the ONU flow channel
2205 f.incomingFlows[onuID] <- flowCb
2206 // Wait on the channel for flow handlers return value
2207 err := <-errChan
2208 logger.Infow(ctx, "process-flow-received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
2209 return err
2210 }
2211 logger.Errorw(ctx, "flow handler routine not active for onu", log.Fields{"onuID": onuID, "ponPortIdx": f.ponPortIdx})
2212 return fmt.Errorf("flow-handler-routine-not-active-for-onu-%v-pon-%d", onuID, f.ponPortIdx)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002213}
2214
2215// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2216// 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 -08002217func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(handlerRoutineIndex int, subscriberFlowChannel chan flowControlBlock, stopHandler chan bool) {
2218 var flowCb flowControlBlock
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002219 for {
Girish Gowdrada69ec12021-11-16 15:04:58 -08002220 select {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002221 // block on the channel to receive an incoming flow
2222 // process the flow completely before proceeding to handle the next flow
Girish Gowdrada69ec12021-11-16 15:04:58 -08002223 case flowCb = <-subscriberFlowChannel:
2224 if flowCb.addFlow {
2225 logger.Info(flowCb.ctx, "adding-flow-start")
2226 startTime := time.Now()
2227 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2228 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2229 // Pass the return value over the return channel
2230 *flowCb.errChan <- err
2231 } else {
2232 logger.Info(flowCb.ctx, "removing-flow-start")
2233 startTime := time.Now()
2234 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2235 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2236 // Pass the return value over the return channel
2237 *flowCb.errChan <- err
2238 }
2239 case <-stopHandler:
2240 f.flowHandlerRoutineActive[handlerRoutineIndex] = false
2241 return
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002242 }
2243 }
2244}
2245
Girish Gowdrada69ec12021-11-16 15:04:58 -08002246// StopAllFlowHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
2247func (f *OpenOltFlowMgr) StopAllFlowHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
2248 for i, v := range f.stopFlowHandlerRoutine {
2249 if f.flowHandlerRoutineActive[i] {
2250 select {
2251 case v <- true:
2252 case <-time.After(time.Second * 5):
2253 logger.Warnw(ctx, "timeout stopping flow handler routine", log.Fields{"onuID": i, "deviceID": f.deviceHandler.device.Id})
2254 }
2255 }
2256 }
2257 wg.Done()
2258 logger.Debugw(ctx, "stopped all flow handler routines", log.Fields{"ponPortIdx": f.ponPortIdx})
2259}
2260
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002261// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302262// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002263func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002264 classifierInfo := make(map[string]interface{})
2265 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002266 var UsMeterID uint32
2267 var DsMeterID uint32
2268
Neha Sharma96b7bf22020-06-15 10:37:32 +00002269 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302270 log.Fields{
2271 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002272 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002273 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002274
Neha Sharma96b7bf22020-06-15 10:37:32 +00002275 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002276 if err != nil {
2277 // Error logging is already done in the called function
2278 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002279 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302280 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002281
Esin Karamanccb714b2019-11-29 15:02:06 +00002282 if flows.HasGroup(flow) {
2283 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002284 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002285 }
2286
manikkaraj k17652a72019-05-06 09:06:36 -04002287 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002288 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002289 if err != nil {
2290 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002291 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002292 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002293
Neha Sharma96b7bf22020-06-15 10:37:32 +00002294 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302295 log.Fields{
2296 "classifierinfo_inport": classifierInfo[InPort],
2297 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002298 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002299
Humera Kouser94d7a842019-08-25 19:04:32 -04002300 if ethType, ok := classifierInfo[EthType]; ok {
2301 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002302 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002303 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002304 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002305 if ethType.(uint32) == PPPoEDEthType {
2306 if voltha.Port_ETHERNET_NNI == IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
2307 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2308 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2309 }
2310 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002311 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002312 if ipProto, ok := classifierInfo[IPProto]; ok {
2313 if ipProto.(uint32) == IPProtoDhcp {
2314 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302315 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002316 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002317 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002318 }
2319 }
2320 }
2321 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002322 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002323 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002324 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002325 }
A R Karthick1f85b802019-10-11 05:06:05 +00002326
npujarec5762e2020-01-01 14:08:48 +05302327 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002328 // also update flowmgr cache
2329 f.onuGemInfoLock.Lock()
2330 onugem, ok := f.onuGemInfoMap[onuID]
2331 if ok {
2332 found := false
2333 for _, uni := range onugem.UniPorts {
2334 if uni == portNo {
2335 found = true
2336 break
2337 }
2338 }
2339 if !found {
2340 onugem.UniPorts = append(onugem.UniPorts, portNo)
2341 f.onuGemInfoMap[onuID] = onugem
2342 logger.Infow(ctx, "added uni port to onugem cache", log.Fields{"uni": portNo})
2343 }
2344 }
2345 f.onuGemInfoLock.Unlock()
A R Karthick1f85b802019-10-11 05:06:05 +00002346
Neha Sharma96b7bf22020-06-15 10:37:32 +00002347 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002348 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302349 return olterrors.NewErrNotFound("tpid-for-flow",
2350 log.Fields{
2351 "flow": flow,
2352 "intf-id": IntfID,
2353 "onu-id": onuID,
2354 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002355 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002356 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302357 log.Fields{
2358 "tp-id": TpID,
2359 "intf-id": intfID,
2360 "onu-id": onuID,
2361 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002362 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002363 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002364 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002365 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002366 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002367 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002368
2369 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002370 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002371}
Girish Gowdra3d633032019-12-10 16:37:05 +05302372
Esin Karamanccb714b2019-11-29 15:02:06 +00002373// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002374func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Andrea Campanella8f645562021-10-28 11:50:56 +05302375 classifierInfo[PacketTagType] = getPacketTypeFromClassifiers(classifierInfo)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002376 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302377 "classifier-info": classifierInfo,
2378 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002379
Esin Karaman65409d82020-03-18 10:58:18 +00002380 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002381 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002382 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002383 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002384
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002385 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002386
David K. Bainbridge794735f2020-02-11 21:01:37 -08002387 onuID := NoneOnuID
2388 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002389
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002390 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002391 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002392 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002393 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002394 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2395 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002396 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002397 }
2398 groupID := actionInfo[GroupID].(uint32)
2399 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002400 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002401 FlowType: Multicast,
2402 NetworkIntfId: int32(networkInterfaceID),
2403 GroupId: groupID,
2404 Classifier: classifierProto,
2405 Priority: int32(flow.Priority),
2406 Cookie: flow.Cookie}
2407
Kent Hagermane6ff1012020-07-14 15:07:53 -04002408 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002409 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002410 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002411 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002412 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002413 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002414 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002415 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002416 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002417 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002418 //cached group can be removed now
2419 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002420 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002421 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002422 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002423
David K. Bainbridge794735f2020-02-11 21:01:37 -08002424 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002425}
2426
Esin Karaman65409d82020-03-18 10:58:18 +00002427//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2428func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2429 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002430 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002431 if err != nil {
2432 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2433 }
2434 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002435 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002436
2437 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2438 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002439}
2440
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002441//sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002442func (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 -07002443
Neha Sharma96b7bf22020-06-15 10:37:32 +00002444 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302445 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002446 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302447 log.Fields{
2448 "intf-id": intfID,
2449 "onu-id": onuID,
2450 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002451 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302452 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002453 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002454
Neha Sharma96b7bf22020-06-15 10:37:32 +00002455 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002456 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{
2457 UniId: uniID,
2458 TpInstancePath: tpPath,
2459 TechTpInstance: &ic.InterAdapterTechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
2460 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002461 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002462 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
manikkaraj k17652a72019-05-06 09:06:36 -04002463 tpDownloadMsg,
2464 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03002465 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002466 onuDev.deviceType,
2467 onuDev.deviceID,
2468 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002469 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302470 return olterrors.NewErrCommunication("send-techprofile-download-request",
2471 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03002472 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05302473 "to-adapter": onuDev.deviceType,
2474 "onu-id": onuDev.deviceID,
2475 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002476 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002477 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302478 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302479}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002480
Girish Gowdra37f13fa2021-08-16 10:59:45 -07002481//AddOnuInfoToFlowMgrCacheAndKvStore function adds onu info to cache and kvstore
2482func (f *OpenOltFlowMgr) AddOnuInfoToFlowMgrCacheAndKvStore(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302483
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002484 f.onuGemInfoLock.RLock()
2485 _, ok := f.onuGemInfoMap[onuID]
2486 f.onuGemInfoLock.RUnlock()
Girish Gowdra9602eb42020-09-09 15:50:39 -07002487 // If the ONU already exists in onuGemInfo list, nothing to do
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002488 if ok {
2489 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2490 log.Fields{"onuID": onuID,
2491 "serialNum": serialNum})
2492 return nil
Girish Gowdra9602eb42020-09-09 15:50:39 -07002493 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002494
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002495 onuGemInfo := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2496 f.onuGemInfoLock.Lock()
2497 f.onuGemInfoMap[onuID] = &onuGemInfo
2498 f.onuGemInfoLock.Unlock()
2499 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onuID, onuGemInfo); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002500 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302501 }
Girish Gowdra37f13fa2021-08-16 10:59:45 -07002502 logger.Infow(ctx, "added-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302503 log.Fields{
2504 "intf-id": intfID,
2505 "onu-id": onuID,
2506 "serial-num": serialNum,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002507 "onu": onuGemInfo,
Shrey Baid26912972020-04-16 21:02:31 +05302508 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002509 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002510}
2511
Girish Gowdra37f13fa2021-08-16 10:59:45 -07002512//RemoveOnuInfoFromFlowMgrCacheAndKvStore function adds onu info to cache and kvstore
2513func (f *OpenOltFlowMgr) RemoveOnuInfoFromFlowMgrCacheAndKvStore(ctx context.Context, intfID uint32, onuID uint32) error {
2514
2515 f.onuGemInfoLock.Lock()
2516 delete(f.onuGemInfoMap, onuID)
2517 f.onuGemInfoLock.Unlock()
2518
2519 if err := f.resourceMgr.DelOnuGemInfo(ctx, intfID, onuID); err != nil {
2520 return err
2521 }
2522 logger.Infow(ctx, "deleted-onuinfo",
2523 log.Fields{
2524 "intf-id": intfID,
2525 "onu-id": onuID,
2526 "device-id": f.deviceHandler.device.Id})
2527 return nil
2528}
2529
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302530//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302531func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002532
Neha Sharma96b7bf22020-06-15 10:37:32 +00002533 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302534 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002535 "gem-port-id": gemPort,
2536 "intf-id": intfID,
2537 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002538 "device-id": f.deviceHandler.device.Id})
2539 f.onuGemInfoLock.RLock()
2540 onugem, ok := f.onuGemInfoMap[onuID]
2541 f.onuGemInfoLock.RUnlock()
2542 if !ok {
2543 logger.Warnw(ctx, "onu gem info is missing", log.Fields{
2544 "gem-port-id": gemPort,
2545 "intf-id": intfID,
2546 "onu-id": onuID,
2547 "device-id": f.deviceHandler.device.Id})
2548 return
2549 }
2550
2551 if onugem.OnuID == onuID {
2552 // check if gem already exists , else update the cache and kvstore
2553 for _, gem := range onugem.GemPorts {
2554 if gem == gemPort {
2555 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
2556 log.Fields{
2557 "gem": gemPort,
2558 "device-id": f.deviceHandler.device.Id})
2559 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302560 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302561 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002562 onugem.GemPorts = append(onugem.GemPorts, gemPort)
2563 f.onuGemInfoLock.Lock()
2564 f.onuGemInfoMap[onuID] = onugem
2565 f.onuGemInfoLock.Unlock()
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002566 logger.Debugw(ctx, "updated onu gem info from cache", log.Fields{"onugem": onugem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002567 } else {
2568 logger.Warnw(ctx, "mismatched onu id", log.Fields{
2569 "gem-port-id": gemPort,
2570 "intf-id": intfID,
2571 "onu-id": onuID,
2572 "device-id": f.deviceHandler.device.Id})
2573 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302574 }
npujarec5762e2020-01-01 14:08:48 +05302575 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302576 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002577 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302578 log.Fields{
2579 "intf-id": intfID,
2580 "onu-id": onuID,
2581 "gemPort": gemPort,
2582 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002583 return
2584 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002585 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302586 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002587 "gem-port-id": gemPort,
2588 "intf-id": intfID,
2589 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002590 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002591}
2592
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002593//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302594func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002595 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002596
2597 if packetIn.IntfType == "pon" {
2598 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002599 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002600 onuID, uniID := packetIn.OnuId, packetIn.UniId
2601 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 +00002602
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002603 if packetIn.PortNo != 0 {
2604 logicalPortNum = packetIn.PortNo
2605 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002606 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002607 }
2608 // 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 +00002609 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002610 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002611 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002612 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002613
2614 if logger.V(log.DebugLevel) {
2615 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2616 log.Fields{
2617 "logical-port-num": logicalPortNum,
2618 "intf-type": packetIn.IntfType,
2619 "packet": hex.EncodeToString(packetIn.Pkt),
2620 })
2621 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002622 return logicalPortNum, nil
2623}
2624
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002625//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002626func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002627 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002628
2629 ctag, priority, err := getCTagFromPacket(ctx, packet)
2630 if err != nil {
2631 return 0, err
2632 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302633
Esin Karaman7fb80c22020-07-16 14:23:33 +00002634 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002635 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002636 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002637 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002638 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302639 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002640 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302641 log.Fields{
2642 "pktinkey": pktInkey,
2643 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002644
2645 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002646 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302647 //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 +00002648 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302649 if err == nil {
2650 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002651 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302652 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002653 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002654 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302655 log.Fields{
2656 "pktinkey": pktInkey,
2657 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302658 return gemPortID, nil
2659 }
2660 }
Shrey Baid26912972020-04-16 21:02:31 +05302661 return uint32(0), olterrors.NewErrNotFound("gem-port",
2662 log.Fields{
2663 "pktinkey": pktInkey,
2664 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002665
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002666}
2667
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002668func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2669 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002670 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002671 classifier[PacketTagType] = DoubleTag
2672 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002673 /* We manage flowId resource pool on per PON port basis.
2674 Since this situation is tricky, as a hack, we pass the NNI port
2675 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002676 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002677 on NNI port, use onu_id as -1 (invalid)
2678 ****************** CAVEAT *******************
2679 This logic works if the NNI Port Id falls within the same valid
2680 range of PON Port Ids. If this doesn't work for some OLT Vendor
2681 we need to have a re-look at this.
2682 *********************************************
2683 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002684 onuID := -1
2685 uniID := -1
2686 gemPortID := -1
2687 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002688 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302689 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302690 return olterrors.NewErrNotFound("nni-intreface-id",
2691 log.Fields{
2692 "classifier": classifier,
2693 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002694 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302695 }
2696
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002697 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002698 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002699 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002700 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002701
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002702 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2703 log.Fields{
2704 "classifier": classifier,
2705 "action": action,
2706 "flowId": logicalFlow.Id,
2707 "intf-id": networkInterfaceID})
2708
David K. Bainbridge794735f2020-02-11 21:01:37 -08002709 classifierProto, err := makeOpenOltClassifierField(classifier)
2710 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002711 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002712 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002713 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002714 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002715 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002716 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002717 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002718 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002719 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2720 OnuId: int32(onuID), // OnuId not required
2721 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002722 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002723 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002724 AllocId: int32(allocID), // AllocId not used
2725 NetworkIntfId: int32(networkInterfaceID),
2726 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002727 Classifier: classifierProto,
2728 Action: actionProto,
2729 Priority: int32(logicalFlow.Priority),
2730 Cookie: logicalFlow.Cookie,
2731 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002732 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002733 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002734 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002735 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002736 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002737}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002738
Esin Karamanae41e2b2019-12-17 18:13:13 +00002739//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2740func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2741 var packetType string
2742 ovid, ivid := false, false
2743 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2744 vid := vlanID & VlanvIDMask
2745 if vid != ReservedVlan {
2746 ovid = true
2747 }
2748 }
2749 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2750 vid := uint32(metadata)
2751 if vid != ReservedVlan {
2752 ivid = true
2753 }
2754 }
2755 if ovid && ivid {
2756 packetType = DoubleTag
2757 } else if !ovid && !ivid {
2758 packetType = Untagged
2759 } else {
2760 packetType = SingleTag
2761 }
2762 return packetType
2763}
2764
2765//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002766func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002767 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002768 action := make(map[string]interface{})
2769 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2770 action[TrapToHost] = true
2771 /* We manage flowId resource pool on per PON port basis.
2772 Since this situation is tricky, as a hack, we pass the NNI port
2773 index (network_intf_id) as PON port Index for the flowId resource
2774 pool. Also, there is no ONU Id available for trapping packets
2775 on NNI port, use onu_id as -1 (invalid)
2776 ****************** CAVEAT *******************
2777 This logic works if the NNI Port Id falls within the same valid
2778 range of PON Port Ids. If this doesn't work for some OLT Vendor
2779 we need to have a re-look at this.
2780 *********************************************
2781 */
2782 onuID := -1
2783 uniID := -1
2784 gemPortID := -1
2785 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002786 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002787 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302788 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002789 "classifier": classifier,
2790 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002791 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002792 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002793 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002794 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002795 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002796 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002797
David K. Bainbridge794735f2020-02-11 21:01:37 -08002798 classifierProto, err := makeOpenOltClassifierField(classifier)
2799 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002800 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002801 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002802 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002803 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002804 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002805 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002806 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002807 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002808 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2809 OnuId: int32(onuID), // OnuId not required
2810 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002811 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002812 FlowType: Downstream,
2813 AllocId: int32(allocID), // AllocId not used
2814 NetworkIntfId: int32(networkInterfaceID),
2815 GemportId: int32(gemPortID), // GemportId not used
2816 Classifier: classifierProto,
2817 Action: actionProto,
2818 Priority: int32(logicalFlow.Priority),
2819 Cookie: logicalFlow.Cookie,
2820 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002821 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002822 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002823 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002824 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002825
David K. Bainbridge794735f2020-02-11 21:01:37 -08002826 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002827}
2828
salmansiddiqui7ac62132019-08-22 03:58:50 +00002829func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2830 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302831 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002832 }
2833 if Dir == tp_pb.Direction_UPSTREAM {
2834 return "upstream", nil
2835 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2836 return "downstream", nil
2837 }
2838 return "", nil
2839}
2840
Kent Hagermane6ff1012020-07-14 15:07:53 -04002841// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302842func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002843 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002844 tpID uint32, uni string) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002845 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002846 intfID := args[IntfID]
2847 onuID := args[OnuID]
2848 uniID := args[UniID]
2849 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002850 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002851 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002852 gemToAes := make(map[uint32]bool)
2853
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002854 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002855 var direction = tp_pb.Direction_UPSTREAM
2856 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002857 case *tp_pb.TechProfileInstance:
Gamze Abaka7650be62021-02-26 10:50:36 +00002858 if IsUpstream(actionInfo[Output].(uint32)) {
2859 attributes = TpInst.UpstreamGemPortAttributeList
2860 } else {
2861 attributes = TpInst.DownstreamGemPortAttributeList
2862 direction = tp_pb.Direction_DOWNSTREAM
2863 }
2864 default:
2865 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
2866 return
2867 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002868
2869 if len(gemPorts) == 1 {
2870 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002871 gemPortID = gemPorts[0]
2872 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002873 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2874 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002875 pBitMap := attributes[idx].PbitMap
2876 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2877 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2878 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
2879 // this pcp bit traffic.
2880 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2881 if pbitSet == pbit1 {
2882 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2883 pbitToGem[pcp] = gemID
2884 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002885 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002886 }
2887 }
2888 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002889 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2890 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2891 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002892 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002893 }
2894
Gamze Abaka7650be62021-02-26 10:50:36 +00002895 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2896 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2897
salmansiddiqui7ac62132019-08-22 03:58:50 +00002898 if ipProto, ok := classifierInfo[IPProto]; ok {
2899 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002900 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002901 "tp-id": tpID,
2902 "alloc-id": allocID,
2903 "intf-id": intfID,
2904 "onu-id": onuID,
2905 "uni-id": uniID,
2906 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002907 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002908 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002909 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002910 }
2911
Girish Gowdra32625212020-04-29 11:26:35 -07002912 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002913 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302914 log.Fields{
2915 "intf-id": intfID,
2916 "onu-id": onuID,
2917 "uni-id": uniID,
2918 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002919 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002920 logger.Warn(ctx, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002921 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002922 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002923 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002924 return
2925 }
2926 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002927 if ethType.(uint32) == EapEthType {
2928 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002929 "intf-id": intfID,
2930 "onu-id": onuID,
2931 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002932 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002933 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002934 var vlanID uint32
2935 if val, ok := classifierInfo[VlanVid]; ok {
2936 vlanID = (val.(uint32)) & VlanvIDMask
2937 } else {
2938 vlanID = DefaultMgmtVlan
2939 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002940 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002941 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002942 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002943 } else if ethType.(uint32) == PPPoEDEthType {
2944 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2945 "tp-id": tpID,
2946 "alloc-id": allocID,
2947 "intf-id": intfID,
2948 "onu-id": onuID,
2949 "uni-id": uniID,
2950 })
2951 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002952 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002953 logger.Warn(ctx, err)
2954 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002955 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002956 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002957 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002958 "intf-id": intfID,
2959 "onu-id": onuID,
2960 "uni-id": uniID,
2961 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002962 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002963 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002964 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002965 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002966 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002967 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002968 "intf-id": intfID,
2969 "onu-id": onuID,
2970 "uni-id": uniID,
2971 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002972 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002973 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002974 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002975 }
2976 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002977 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05302978 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002979 "intf-id": intfID,
2980 "onu-id": onuID,
2981 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05302982 "classifier": classifierInfo,
2983 "action": actionInfo,
2984 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002985 return
2986 }
2987 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002988 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002989 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002990 logger.Warn(ctx, err)
2991 }
2992 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002993}
2994
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002995func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002996 f.gemToFlowIDsKey.RLock()
2997 flowIDList := f.gemToFlowIDs[gemPortID]
2998 f.gemToFlowIDsKey.RUnlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002999 return len(flowIDList) > 1
3000
Gamze Abakafee36392019-10-03 11:17:24 +00003001}
3002
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003003func (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 +05303004 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00003005 tpGemPorts := tpInst.UpstreamGemPortAttributeList
3006 for _, currentGemPort := range currentGemPorts {
3007 for _, tpGemPort := range tpGemPorts {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003008 if (currentGemPort == tpGemPort.GemportId) && (currentGemPort != gemPortID) {
Gamze Abakafee36392019-10-03 11:17:24 +00003009 return true, currentGemPort
3010 }
3011 }
3012 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00003013 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
3014 return false, 0
3015}
Girish Gowdra54934262019-11-13 14:19:55 +05303016
Gamze Abakacb0e6772021-06-10 08:32:12 +00003017func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003018 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
3019 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
3020 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 +00003021 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303022 for i := 0; i < len(tpInstances); i++ {
3023 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00003024 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003025 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Gamze Abakacb0e6772021-06-10 08:32:12 +00003026 logger.Debugw(ctx, "alloc-is-in-use",
3027 log.Fields{
3028 "device-id": f.deviceHandler.device.Id,
3029 "intfID": sq.intfID,
3030 "onuID": sq.onuID,
3031 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003032 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00003033 })
3034 return true
Girish Gowdra54934262019-11-13 14:19:55 +05303035 }
3036 }
3037 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00003038 return false
Gamze Abakafee36392019-10-03 11:17:24 +00003039}
3040
Neha Sharma96b7bf22020-06-15 10:37:32 +00003041func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003042 for _, field := range flows.GetOfbFields(flow) {
3043 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003044 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003045 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003046 } else if field.Type == flows.ETH_DST {
3047 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003048 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003049 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003050 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003051 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003052 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003053 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003054 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003055 } else if field.Type == flows.VLAN_VID {
Andrea Campanella8f645562021-10-28 11:50:56 +05303056 // The ReservedVlan is used to signify transparent vlan. Do not do any classification when we see ReservedVlan
3057 if field.GetVlanVid() != ReservedVlan {
3058 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
3059 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
3060 }
Scott Baker355d1742019-10-24 10:57:52 -07003061 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003062 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003063 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003064 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003065 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003066 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003067 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003068 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003069 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003070 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003071 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003072 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003073 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003074 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003075 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003076 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003077 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003078 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003079 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003080 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003081 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003082 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003083 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003084 return
3085 }
3086 }
3087}
3088
Neha Sharma96b7bf22020-06-15 10:37:32 +00003089func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003090 for _, action := range flows.GetActions(flow) {
3091 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003092 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003093 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003094 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003095 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003096 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003097 }
Scott Baker355d1742019-10-24 10:57:52 -07003098 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003099 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003100 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003101 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003102 if out := action.GetPush(); out != nil {
3103 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003104 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003105 } else {
3106 actionInfo[PushVlan] = true
3107 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003108 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303109 log.Fields{
3110 "push-tpid": actionInfo[TPID].(uint32),
3111 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003112 }
3113 }
Scott Baker355d1742019-10-24 10:57:52 -07003114 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003115 if out := action.GetSetField(); out != nil {
3116 if field := out.GetField(); field != nil {
3117 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003118 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003119 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003120 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3121 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003122 }
3123 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003124 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003125 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003126 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003127 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003128 }
3129 }
3130 return nil
3131}
3132
Neha Sharma96b7bf22020-06-15 10:37:32 +00003133func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003134 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003135 fieldtype := ofbField.GetType()
3136 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003137 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3138 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003139 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003140 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003141 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003142 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003143 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3144 pcp := ofbField.GetVlanPcp()
3145 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003146 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003147 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003148 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003149 }
3150 }
3151}
3152
Neha Sharma96b7bf22020-06-15 10:37:32 +00003153func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003154 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003155 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003156 } else {
3157 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003158 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003159 }
3160}
3161
Neha Sharma96b7bf22020-06-15 10:37:32 +00003162func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003163 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003164 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003165 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3166 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003167 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003168 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003169 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303170 log.Fields{
3171 "newinport": classifierInfo[InPort].(uint32),
3172 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003173 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303174 return olterrors.NewErrNotFound("child-in-port",
3175 log.Fields{
3176 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3177 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003178 }
3179 }
3180 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003181 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003182 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003183 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003184 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003185 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003186 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303187 log.Fields{
3188 "newoutport": actionInfo[Output].(uint32),
3189 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003190 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303191 return olterrors.NewErrNotFound("out-port",
3192 log.Fields{
3193 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3194 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003195 }
3196 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3197 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003198 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003199 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003200 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303201 log.Fields{
3202 "newinport": actionInfo[Output].(uint32),
3203 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003204 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303205 return olterrors.NewErrNotFound("nni-port",
3206 log.Fields{
3207 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3208 "in-port": classifierInfo[InPort].(uint32),
3209 "out-port": actionInfo[Output].(uint32),
3210 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003211 }
3212 }
3213 }
3214 return nil
3215}
Gamze Abakafee36392019-10-03 11:17:24 +00003216
Neha Sharma96b7bf22020-06-15 10:37:32 +00003217func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003218 /* Metadata 8 bytes:
3219 Most Significant 2 Bytes = Inner VLAN
3220 Next 2 Bytes = Tech Profile ID(TPID)
3221 Least Significant 4 Bytes = Port ID
3222 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3223 subscriber related flows.
3224 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003225 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003226 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003227 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003228 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003229 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003230 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003231}
3232
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003233func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3234 for _, sliceElement := range slice {
3235 if sliceElement == item {
3236 return slice
3237 }
3238 }
3239 return append(slice, item)
3240}
3241
3242func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003243 for _, sliceElement := range slice {
3244 if sliceElement == item {
3245 return slice
3246 }
3247 }
3248 return append(slice, item)
3249}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303250
3251// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003252func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303253
3254 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3255 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003256 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003257 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003258 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003259 log.Fields{
3260 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003261 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003262 return uint32(0), err
3263 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003264 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303265 return intfID, nil
3266 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003267 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003268 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003269 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003270 log.Fields{
3271 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003272 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003273 return uint32(0), err
3274 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003275 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303276 return intfID, nil
3277 }
3278 return uint32(0), nil
3279}
3280
3281// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003282func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3283 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3284 if err != nil {
3285 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3286 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3287 return
3288 }
3289 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003290
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003291 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003292 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003293 f.packetInGemPortLock.RUnlock()
3294
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303295 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003296 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003297 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 +05303298 log.Fields{
3299 "pktinkey": pktInkey,
3300 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003301 return
3302 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303303 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003304 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003305 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003306 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003307
npujarec5762e2020-01-01 14:08:48 +05303308 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003309 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 +05303310 log.Fields{
3311 "pktinkey": pktInkey,
3312 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303313}
3314
Esin Karaman7fb80c22020-07-16 14:23:33 +00003315//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3316func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3317 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003318 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003319 return 0, 0, errors.New("invalid packet length")
3320 }
3321 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3322 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3323
3324 var index int8
3325 if outerEthType == 0x8100 {
3326 if innerEthType == 0x8100 {
3327 // q-in-q 802.1ad or 802.1q double tagged packet.
3328 // get the inner vlanId
3329 index = 18
3330 } else {
3331 index = 14
3332 }
3333 priority := (packet[index] >> 5) & 0x7
3334 //13 bits composes vlanId value
3335 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3336 return vlan, priority, nil
3337 }
3338 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3339 return 0, 0, nil
3340}
3341
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003342func (f *OpenOltFlowMgr) loadFlowIDsForGemAndGemIDsForFlow(ctx context.Context) {
3343 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - start")
3344 f.onuGemInfoLock.RLock()
3345 f.gemToFlowIDsKey.Lock()
3346 f.flowIDToGemsLock.Lock()
3347 for _, og := range f.onuGemInfoMap {
3348 for _, gem := range og.GemPorts {
3349 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, f.ponPortIdx, gem)
Gamze Abaka3e268512021-09-08 01:14:33 +00003350 if err == nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003351 f.gemToFlowIDs[gem] = flowIDs
3352 for _, flowID := range flowIDs {
3353 if _, ok := f.flowIDToGems[flowID]; !ok {
3354 f.flowIDToGems[flowID] = []uint32{gem}
3355 } else {
3356 f.flowIDToGems[flowID] = appendUnique32bit(f.flowIDToGems[flowID], gem)
3357 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303358 }
3359 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303360 }
3361 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003362 f.flowIDToGemsLock.Unlock()
3363 f.gemToFlowIDsKey.Unlock()
3364 f.onuGemInfoLock.RUnlock()
3365 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - end")
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303366}
Esin Karamanccb714b2019-11-29 15:02:06 +00003367
Girish Gowdra9602eb42020-09-09 15:50:39 -07003368//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3369// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003370func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003371 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003372 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3373 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003374 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003375 "flow-id": flow.Id,
3376 "device-id": f.deviceHandler.device.Id})
3377 // Remove from device
3378 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3379 // DKB
3380 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3381 log.Fields{
3382 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003383 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003384 return err
3385 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003386
3387 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003388}
3389
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003390func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, ponID uint32, onuID uint32, uniID uint32) *ic.InterAdapterTechProfileDownloadMessage {
3391 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003392 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003393 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
3394 return nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003395 }
3396
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003397 switch tpInst := tpInst.(type) {
3398 case *tp_pb.TechProfileInstance:
3399 logger.Debugw(ctx, "fetched-tp-instance-successfully--formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
3400 return &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID,
3401 TpInstancePath: tpPath,
3402 TechTpInstance: &ic.InterAdapterTechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003403 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003404 case *openoltpb2.EponTechProfileInstance:
3405 return &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID,
3406 TpInstancePath: tpPath,
3407 TechTpInstance: &ic.InterAdapterTechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
3408 }
3409 default:
3410 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003411 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003412 return nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003413}
3414
Girish Gowdrabcf98af2021-07-01 08:24:42 -07003415func (f *OpenOltFlowMgr) getOnuGemInfoList(ctx context.Context) []rsrcMgr.OnuGemInfo {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003416 var onuGemInfoLst []rsrcMgr.OnuGemInfo
3417 f.onuGemInfoLock.RLock()
3418 defer f.onuGemInfoLock.RUnlock()
3419 for _, v := range f.onuGemInfoMap {
3420 onuGemInfoLst = append(onuGemInfoLst, *v)
3421 }
3422 return onuGemInfoLst
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003423}