blob: d0a9875511b675df6cedc2cc97569f0e11a5ed67 [file] [log] [blame]
manikkaraj kbf256be2019-03-25 00:13:48 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
manikkaraj kbf256be2019-03-25 00:13:48 +053019
20import (
21 "context"
Matteo Scandolo6056e822019-11-13 14:05:29 -080022 "encoding/hex"
Girish Gowdracefae192020-03-19 18:14:10 -070023 "errors"
manikkaraj kbf256be2019-03-25 00:13:48 +053024 "fmt"
Gamze Abaka7650be62021-02-26 10:50:36 +000025 "strconv"
serkant.uluderya4aff1862020-09-17 23:35:26 +030026 "strings"
27 "sync"
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070028 "time"
serkant.uluderya4aff1862020-09-17 23:35:26 +030029
Mahir Gunyel1d20eff2021-07-04 15:39:36 -070030 "github.com/opencord/voltha-lib-go/v5/pkg/meters"
31
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070032 "github.com/opencord/voltha-lib-go/v5/pkg/flows"
33 "github.com/opencord/voltha-lib-go/v5/pkg/log"
34 tp "github.com/opencord/voltha-lib-go/v5/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080035 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070036 "github.com/opencord/voltha-protos/v4/go/common"
37 ic "github.com/opencord/voltha-protos/v4/go/inter_container"
38 ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
39 openoltpb2 "github.com/opencord/voltha-protos/v4/go/openolt"
40 tp_pb "github.com/opencord/voltha-protos/v4/go/tech_profile"
41 "github.com/opencord/voltha-protos/v4/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040042
Thomas Lee S94109f12020-03-03 16:39:29 +053043 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000044 "google.golang.org/grpc/codes"
45 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053046)
47
48const (
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070049 //IPProtoDhcp flow category
50 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053051
Girish Gowdraa09aeab2020-09-14 16:30:52 -070052 //IgmpProto proto value
53 IgmpProto = 2
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070054
55 //EapEthType eapethtype value
56 EapEthType = 0x888e
57 //LldpEthType lldp ethtype value
58 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000059 //IPv4EthType IPv4 ethernet type value
60 IPv4EthType = 0x800
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -030061 //PPPoEDEthType PPPoE discovery ethernet type value
62 PPPoEDEthType = 0x8863
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070063
Andrea Campanella7acc0b92020-02-14 09:20:49 +010064 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
65 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040066
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070067 //DefaultMgmtVlan default vlan value
68 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053069
manikkaraj kbf256be2019-03-25 00:13:48 +053070 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070071
David K. Bainbridge82efc492019-09-04 09:57:11 -070072 //Upstream constant
73 Upstream = "upstream"
74 //Downstream constant
75 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000076 //Multicast constant
77 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070078 //PacketTagType constant
79 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070080 //Untagged constant
81 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070082 //SingleTag constant
83 SingleTag = "single_tag"
84 //DoubleTag constant
85 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053086
87 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070088
89 //EthType constant
90 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +000091 //EthDst constant
92 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070093 //TPID constant
94 TPID = "tpid"
95 //IPProto constant
96 IPProto = "ip_proto"
97 //InPort constant
98 InPort = "in_port"
99 //VlanVid constant
100 VlanVid = "vlan_vid"
101 //VlanPcp constant
102 VlanPcp = "vlan_pcp"
103
104 //UDPDst constant
105 UDPDst = "udp_dst"
106 //UDPSrc constant
107 UDPSrc = "udp_src"
108 //Ipv4Dst constant
109 Ipv4Dst = "ipv4_dst"
110 //Ipv4Src constant
111 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700112 //Metadata constant
113 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700114 //TunnelID constant
115 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700116 //Output constant
117 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000118 //GroupID constant
119 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700120 // Actions
121
122 //PopVlan constant
123 PopVlan = "pop_vlan"
124 //PushVlan constant
125 PushVlan = "push_vlan"
126 //TrapToHost constant
127 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400128 //MaxMeterBand constant
129 MaxMeterBand = 2
130 //VlanPCPMask contant
131 VlanPCPMask = 0xFF
132 //VlanvIDMask constant
133 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000134 //IntfID constant
135 IntfID = "intfId"
136 //OnuID constant
137 OnuID = "onuId"
138 //UniID constant
139 UniID = "uniId"
140 //PortNo constant
141 PortNo = "portNo"
142 //AllocID constant
143 AllocID = "allocId"
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000144 //GemID constant
145 GemID = "gemId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000146
147 //NoneOnuID constant
148 NoneOnuID = -1
149 //NoneUniID constant
150 NoneUniID = -1
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700151
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700152 // Max number of flows that can be queued per ONU
153 maxConcurrentFlowsPerOnu = 20
manikkaraj kbf256be2019-03-25 00:13:48 +0530154
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700155 bitMapPrefix = "0b"
156 pbit1 = '1'
157)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400158
Gamze Abakafee36392019-10-03 11:17:24 +0000159type schedQueue struct {
160 direction tp_pb.Direction
161 intfID uint32
162 onuID uint32
163 uniID uint32
164 tpID uint32
165 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700166 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000167 meterID uint32
168 flowMetadata *voltha.FlowMetadata
169}
170
Gamze Abaka7650be62021-02-26 10:50:36 +0000171type flowContext struct {
172 intfID uint32
173 onuID uint32
174 uniID uint32
175 portNo uint32
176 classifier map[string]interface{}
177 action map[string]interface{}
178 logicalFlow *ofp.OfpFlowStats
179 allocID uint32
180 gemPortID uint32
181 tpID uint32
182 pbitToGem map[uint32]uint32
183 gemToAes map[uint32]bool
184}
185
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700186// This control block is created per flow add/remove and pushed on the incomingFlows channel slice
187// The flowControlBlock is then picked by the perOnuFlowHandlerRoutine for further processing.
188// There is on perOnuFlowHandlerRoutine routine per ONU that constantly monitors for any incoming
189// flow and processes it serially
190type flowControlBlock struct {
191 ctx context.Context // Flow handler context
192 addFlow bool // if true flow to be added, else removed
193 flow *voltha.OfpFlowStats // Flow message
194 flowMetadata *voltha.FlowMetadata // FlowMetadata that contains flow meter information. This can be nil for Flow remove
195 errChan *chan error // channel to report the Flow handling error
Esin Karamanccb714b2019-11-29 15:02:06 +0000196}
197
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700198//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530199type OpenOltFlowMgr struct {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700200 ponPortIdx uint32 // Pon Port this FlowManager is responsible for
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700201 techprofile tp.TechProfileIf
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700202 deviceHandler *DeviceHandler
203 grpMgr *OpenOltGroupMgr
204 resourceMgr *rsrcMgr.OpenOltResourceMgr
205
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700206 gemToFlowIDs map[uint32][]uint64 // gem port id to flow ids
207 gemToFlowIDsKey sync.RWMutex // lock to be used to access the gemToFlowIDs map
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700208
209 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
210 packetInGemPortLock sync.RWMutex
211
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700212 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700213 onuGemInfoMap map[uint32]*rsrcMgr.OnuGemInfo //onu, gem and uni info local cache -> map of onuID to OnuGemInfo
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700214 // We need to have a global lock on the onuGemInfo map
Girish Gowdra9602eb42020-09-09 15:50:39 -0700215 onuGemInfoLock sync.RWMutex
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700216
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700217 flowIDToGems map[uint64][]uint32
218 flowIDToGemsLock sync.RWMutex
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700219
220 // Slice of channels. Each channel in slice, index by ONU ID, queues flows per ONU.
221 // A go routine per ONU, waits on the unique channel (indexed by ONU ID) for incoming flows (add/remove)
222 incomingFlows []chan flowControlBlock
manikkaraj kbf256be2019-03-25 00:13:48 +0530223}
224
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700225//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700226func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000227 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530228 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530229 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530230
manikkaraj kbf256be2019-03-25 00:13:48 +0530231 flowMgr.deviceHandler = dh
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700232 flowMgr.ponPortIdx = ponPortIdx
Girish Gowdra9602eb42020-09-09 15:50:39 -0700233 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530234 flowMgr.resourceMgr = rMgr
Neha Sharma96b7bf22020-06-15 10:37:32 +0000235 if err = flowMgr.populateTechProfilePerPonPort(ctx); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700236 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"err": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530237 return nil
238 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700239 flowMgr.gemToFlowIDs = make(map[uint32][]uint64)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530240 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700241 flowMgr.flowIDToGems = make(map[uint64][]uint32)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700242
243 // Create a slice of buffered channels for handling concurrent flows per ONU.
244 // The additional entry (+1) is to handle the NNI trap flows on a separate channel from individual ONUs channel
245 flowMgr.incomingFlows = make([]chan flowControlBlock, MaxOnusPerPon+1)
246 for i := range flowMgr.incomingFlows {
247 flowMgr.incomingFlows[i] = make(chan flowControlBlock, maxConcurrentFlowsPerOnu)
248 // Spin up a go routine to handling incoming flows (add/remove).
249 // There will be on go routine per ONU.
250 // This routine will be blocked on the flowMgr.incomingFlows[onu-id] channel for incoming flows.
251 go flowMgr.perOnuFlowHandlerRoutine(flowMgr.incomingFlows[i])
252 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700253 flowMgr.onuGemInfoMap = make(map[uint32]*rsrcMgr.OnuGemInfo)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530254 //Load the onugem info cache from kv store on flowmanager start
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700255 onuIDStart := flowMgr.deviceHandler.deviceInfo.OnuIdStart
256 onuIDEnd := flowMgr.deviceHandler.deviceInfo.OnuIdEnd
257 for onuID := onuIDStart; onuID <= onuIDEnd; onuID++ {
258 // check for a valid serial number in onuGem as GetOnuGemInfo can return nil error in case of nothing found in the path.
259 onugem, err := rMgr.GetOnuGemInfo(ctx, onuID, ponPortIdx)
260 if err == nil && onugem != nil && onugem.SerialNumber != "" {
261 flowMgr.onuGemInfoMap[onuID] = onugem
262 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530263 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700264
265 //Load flowID list per gem map And gemIDs per flow per interface from the kvstore.
266 flowMgr.loadFlowIDsForGemAndGemIDsForFlow(ctx)
267
Esin Karamanccb714b2019-11-29 15:02:06 +0000268 //load interface to multicast queue map from kv store
Girish Gowdra9602eb42020-09-09 15:50:39 -0700269 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000270 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530271 return &flowMgr
272}
273
Kent Hagermane6ff1012020-07-14 15:07:53 -0400274func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700275 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
276 // Flow is not replicated in this case, we need to register the flow for a single gem-port
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700277 return f.registerFlowIDForGemAndGemIDForFlow(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowFromCore)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700278 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
279 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
280 for _, gemPort := range deviceFlow.PbitToGemport {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700281 if err := f.registerFlowIDForGemAndGemIDForFlow(ctx, uint32(deviceFlow.AccessIntfId), gemPort, flowFromCore); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700282 return err
283 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700284 }
Gamze Abakafee36392019-10-03 11:17:24 +0000285 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700286 return nil
287}
288
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700289func (f *OpenOltFlowMgr) registerFlowIDForGemAndGemIDForFlow(ctx context.Context, accessIntfID uint32, gemPortID uint32, flowFromCore *ofp.OfpFlowStats) error {
290 // update gem->flows map
291 f.gemToFlowIDsKey.Lock()
292 flowIDList, ok := f.gemToFlowIDs[gemPortID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700293 if !ok {
294 flowIDList = []uint64{flowFromCore.Id}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700295 } else {
296 flowIDList = appendUnique64bit(flowIDList, flowFromCore.Id)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700297 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700298 f.gemToFlowIDs[gemPortID] = flowIDList
299 f.gemToFlowIDsKey.Unlock()
300
301 // update flow->gems map
302 f.flowIDToGemsLock.Lock()
303 if _, ok := f.flowIDToGems[flowFromCore.Id]; !ok {
304 f.flowIDToGems[flowFromCore.Id] = []uint32{gemPortID}
305 } else {
306 f.flowIDToGems[flowFromCore.Id] = appendUnique32bit(f.flowIDToGems[flowFromCore.Id], gemPortID)
307 }
308 f.flowIDToGemsLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700309
310 // update the flowids for a gem to the KVstore
311 return f.resourceMgr.UpdateFlowIDsForGem(ctx, accessIntfID, gemPortID, flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400312}
313
Girish Gowdra9602eb42020-09-09 15:50:39 -0700314func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000315 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
Andrea Campanellabfe08432020-09-11 17:07:03 +0200316 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000317 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530318 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700319 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530320
Neha Sharma96b7bf22020-06-15 10:37:32 +0000321 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530322 "device-id": f.deviceHandler.device.Id,
323 "intf-id": intfID,
324 "onu-id": onuID,
325 "uni-id": uniID,
326 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700327 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530328 "action": actionInfo,
329 "usmeter-iD": UsMeterID,
330 "dsmeter-iD": DsMeterID,
331 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400332 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
333 // is because the flow is an NNI flow and there would be no onu resources associated with it
334 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400335 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200336 cause := "no-onu-id-for-flow"
337 fields := log.Fields{
338 "onu": onuID,
339 "port-no": portNo,
340 "classifer": classifierInfo,
341 "action": actionInfo,
342 "device-id": f.deviceHandler.device.Id}
343 logger.Errorw(ctx, cause, fields)
344 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530345 }
346
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700347 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000348 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530349 "uni": uni,
350 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530351
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700352 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
353 "device-id": f.deviceHandler.device.Id,
354 "intf-id": intfID,
355 "onu-id": onuID,
356 "uni-id": uniID,
357 "port-no": portNo,
358 "classifier": classifierInfo,
359 "action": actionInfo,
360 "usmeter-id": UsMeterID,
361 "dsmeter-id": DsMeterID,
362 "tp-id": TpID})
363 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
364 if allocID == 0 || gemPorts == nil || TpInst == nil {
365 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
366 return olterrors.NewErrNotFound(
367 "alloc-id-gem-ports-tp-unavailable",
368 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400369 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700370 args := make(map[string]uint32)
371 args[IntfID] = intfID
372 args[OnuID] = onuID
373 args[UniID] = uniID
374 args[PortNo] = portNo
375 args[AllocID] = allocID
376
377 /* Flows can be added specific to gemport if p-bits are received.
378 * If no pbit mentioned then adding flows for all gemports
379 */
380 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
381
Andrea Campanellabfe08432020-09-11 17:07:03 +0200382 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530383}
384
salmansiddiqui7ac62132019-08-22 03:58:50 +0000385// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530386func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400387
Neha Sharma96b7bf22020-06-15 10:37:32 +0000388 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530389 log.Fields{"dir": sq.direction,
390 "intf-id": sq.intfID,
391 "onu-id": sq.onuID,
392 "uni-id": sq.uniID,
393 "tp-id": sq.tpID,
394 "meter-id": sq.meterID,
395 "tp-inst": sq.tpInst,
396 "flowmetadata": sq.flowMetadata,
397 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400398
Gamze Abakafee36392019-10-03 11:17:24 +0000399 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000400 if err != nil {
401 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400402 }
403
404 /* Lets make a simple assumption that if the meter-id is present on the KV store,
405 * then the scheduler and queues configuration is applied on the OLT device
406 * in the given direction.
407 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000408
Manikkaraj kb1d51442019-07-23 10:41:02 -0400409 var SchedCfg *tp_pb.SchedulerConfig
Girish Gowdraa482f272021-03-24 23:04:19 -0700410 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400411 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530412 return olterrors.NewErrNotFound("meter",
413 log.Fields{"intf-id": sq.intfID,
414 "onu-id": sq.onuID,
415 "uni-id": sq.uniID,
416 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400417 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000418
Girish Gowdraa482f272021-03-24 23:04:19 -0700419 if meterInfo != nil {
420 logger.Debugw(ctx, "scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id, "meter-id": sq.meterID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700421 if meterInfo.MeterID == sq.meterID {
Girish Gowdraa482f272021-03-24 23:04:19 -0700422 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, true); err != nil {
423 return err
424 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400425 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400426 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530427 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800428 "unsupported": "meter-id",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700429 "kv-store-meter-id": meterInfo.MeterID,
Shrey Baid26912972020-04-16 21:02:31 +0530430 "meter-id-in-flow": sq.meterID,
431 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400432 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000433
Neha Sharma96b7bf22020-06-15 10:37:32 +0000434 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530435 log.Fields{
436 "meter-id": sq.meterID,
437 "direction": Direction,
438 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000439
Gamze Abakafee36392019-10-03 11:17:24 +0000440 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700441 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Gamze Abakafee36392019-10-03 11:17:24 +0000442 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700443 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Girish Kumar8f73fe02019-12-09 13:19:37 +0000444 }
445
Girish Gowdraa482f272021-03-24 23:04:19 -0700446 found := false
447 meterInfo = &rsrcMgr.MeterInfo{}
Gamze Abakafee36392019-10-03 11:17:24 +0000448 if sq.flowMetadata != nil {
449 for _, meter := range sq.flowMetadata.Meters {
450 if sq.meterID == meter.MeterId {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700451 meterInfo.MeterID = meter.MeterId
Girish Gowdraa482f272021-03-24 23:04:19 -0700452 meterInfo.RefCnt = 1 // initialize it to 1, since this is the first flow that referenced the meter id.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000453 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700454 log.Fields{"meter": meter,
Shrey Baid26912972020-04-16 21:02:31 +0530455 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -0700456 found = true
Manikkaraj kb1d51442019-07-23 10:41:02 -0400457 break
458 }
459 }
460 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000461 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400462 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700463 if !found {
Thomas Lee S94109f12020-03-03 16:39:29 +0530464 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800465 "reason": "Could-not-get-meterbands-from-flowMetadata",
466 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530467 "meter-id": sq.meterID,
468 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400469 }
Gamze Abaka01174422021-03-10 06:55:27 +0000470
471 var TrafficShaping *tp_pb.TrafficShapingInfo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700472 if TrafficShaping, err = meters.GetTrafficShapingInfo(ctx, sq.flowMetadata.Meters[0]); err != nil {
Gamze Abaka01174422021-03-10 06:55:27 +0000473 return olterrors.NewErrInvalidValue(log.Fields{
474 "reason": "invalid-meter-config",
475 "meter-id": sq.meterID,
476 "device-id": f.deviceHandler.device.Id}, nil)
477 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400478
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700479 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000480 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400481
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700482 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530483 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
484 log.Fields{"intf-id": sq.intfID,
485 "direction": sq.direction,
486 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400487 }
488
salmansiddiqui7ac62132019-08-22 03:58:50 +0000489 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400490 * store the meter id on the KV store, for further reference.
491 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700492 if err := f.resourceMgr.StoreMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530493 return olterrors.NewErrAdapter("failed-updating-meter-id",
494 log.Fields{"onu-id": sq.onuID,
495 "meter-id": sq.meterID,
496 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400497 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000498 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530499 log.Fields{"direction": Direction,
Girish Gowdraa482f272021-03-24 23:04:19 -0700500 "meter-info": meterInfo,
501 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400502 return nil
503}
504
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700505func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700506 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000507
508 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530509 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
510 log.Fields{"intf-id": sq.intfID,
511 "direction": sq.direction,
512 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000513 }
514
Gamze Abakacb0e6772021-06-10 08:32:12 +0000515 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
516 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
517 log.Fields{
518 "direction": sq.direction,
519 "TrafficScheds": TrafficSched,
520 "device-id": f.deviceHandler.device.Id,
521 "intfID": sq.intfID,
522 "onuID": sq.onuID,
523 "uniID": sq.uniID})
524 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
525 IntfId: sq.intfID, OnuId: sq.onuID,
526 UniId: sq.uniID, PortNo: sq.uniPort,
527 TrafficScheds: TrafficSched}); err != nil {
528 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
529 }
530 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
531 "direction": sq.direction,
532 "traffic-queues": trafficQueues,
533 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000534 }
535
536 // On receiving the CreateTrafficQueues request, the driver should create corresponding
537 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000538 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530539 log.Fields{"direction": sq.direction,
540 "traffic-queues": trafficQueues,
541 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530542 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000543 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
544 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000545 TrafficQueues: trafficQueues,
546 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530547 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000548 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000549 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530550 "direction": sq.direction,
551 "traffic-queues": trafficQueues,
552 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000553
Esin Karamanccb714b2019-11-29 15:02:06 +0000554 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700555 multicastTrafficQueues := f.techprofile.GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance))
Esin Karamanccb714b2019-11-29 15:02:06 +0000556 if len(multicastTrafficQueues) > 0 {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700557 if _, present := f.grpMgr.GetInterfaceToMcastQueueMap(sq.intfID); !present { //assumed that there is only one queue per PON for the multicast service
Esin Karamanccb714b2019-11-29 15:02:06 +0000558 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
559 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000560 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000561 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700562 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000563 gemPortID: multicastQueuePerPonPort.GemportId,
564 servicePriority: multicastQueuePerPonPort.Priority,
565 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700566 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000567 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400568 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700569 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400570 return err
571 }
Shrey Baid26912972020-04-16 21:02:31 +0530572
Neha Sharma96b7bf22020-06-15 10:37:32 +0000573 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000574 }
575 }
576 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000577 return nil
578}
579
salmansiddiqui7ac62132019-08-22 03:58:50 +0000580// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530581func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400582
583 var Direction string
584 var SchedCfg *tp_pb.SchedulerConfig
585 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000586 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530587 log.Fields{
588 "direction": sq.direction,
589 "intf-id": sq.intfID,
590 "onu-id": sq.onuID,
591 "uni-id": sq.uniID,
592 "uni-port": sq.uniPort,
593 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000594 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700595 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400596 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000597 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700598 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400599 Direction = "downstream"
600 }
601
Girish Gowdraa482f272021-03-24 23:04:19 -0700602 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
Manikkaraj kb1d51442019-07-23 10:41:02 -0400603
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700604 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000605 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000606
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700607 TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000608 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530609 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
610 log.Fields{
611 "intf-id": sq.intfID,
612 "direction": sq.direction,
613 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000614 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400615
npujarec5762e2020-01-01 14:08:48 +0530616 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000617 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
618 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000619 TrafficQueues: TrafficQueues,
620 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000621 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530622 log.Fields{
623 "intf-id": sq.intfID,
624 "traffic-queues": TrafficQueues,
625 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400626 }
Gamze Abakacb0e6772021-06-10 08:32:12 +0000627 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id, "trafficQueues": TrafficQueues})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400628
Gamze Abakacb0e6772021-06-10 08:32:12 +0000629 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
630 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
631 IntfId: sq.intfID, OnuId: sq.onuID,
632 UniId: sq.uniID, PortNo: sq.uniPort,
633 TrafficScheds: TrafficSched}); err != nil {
634 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
635 log.Fields{
636 "intf-id": sq.intfID,
637 "traffic-schedulers": TrafficSched,
638 "onu-id": sq.onuID,
639 "uni-id": sq.uniID,
640 "uni-port": sq.uniPort}, err)
641 }
642
643 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
644 log.Fields{"device-id": f.deviceHandler.device.Id,
645 "intf-id": sq.intfID,
646 "onu-id": sq.onuID,
647 "uni-id": sq.uniID,
648 "uni-port": sq.uniPort})
649
650 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700651 allocID := sq.tpInst.(*tp_pb.TechProfileInstance).UsScheduler.AllocId
Gamze Abakacb0e6772021-06-10 08:32:12 +0000652 f.resourceMgr.FreeAllocID(ctx, sq.intfID, sq.onuID, sq.uniID, allocID)
653 // Delete the TCONT on the ONU.
654 uni := getUniPortPath(f.deviceHandler.device.Id, sq.intfID, int32(sq.onuID), int32(sq.uniID))
655 tpPath := f.getTPpath(ctx, sq.intfID, uni, sq.tpID)
656 if err := f.sendDeleteTcontToChild(ctx, sq.intfID, sq.onuID, sq.uniID, allocID, tpPath); err != nil {
657 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
658 log.Fields{
659 "intf": sq.intfID,
660 "onu-id": sq.onuID,
661 "uni-id": sq.uniID,
662 "device-id": f.deviceHandler.device.Id,
663 "alloc-id": allocID})
664 }
665 }
666 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000667
668 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400669 * delete the meter id on the KV store.
670 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700671 err = f.resourceMgr.RemoveMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400672 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530673 return olterrors.NewErrAdapter("unable-to-remove-meter",
674 log.Fields{
675 "onu": sq.onuID,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700676 "device-id": f.deviceHandler.device.Id,
677 "intf-id": sq.intfID,
678 "onu-id": sq.onuID,
679 "uni-id": sq.uniID,
680 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400681 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000682 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530683 log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530684 "dir": Direction,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700685 "device-id": f.deviceHandler.device.Id,
686 "intf-id": sq.intfID,
687 "onu-id": sq.onuID,
688 "uni-id": sq.uniID,
689 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400690 return err
691}
692
Gamze Abakafee36392019-10-03 11:17:24 +0000693// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700694func (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 +0000695 var allocIDs []uint32
696 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530697 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530698 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000699 var err error
npujarec5762e2020-01-01 14:08:48 +0530700 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
701 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000702 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530703
Neha Sharma96b7bf22020-06-15 10:37:32 +0000704 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530705 "intf-id": intfID,
706 "onu-id": onuID,
707 "uni-id": uniID,
708 "device-id": f.deviceHandler.device.Id,
709 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530710
Manikkaraj kb1d51442019-07-23 10:41:02 -0400711 // Check tech profile instance already exists for derived port name
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700712 techProfileInstance, _ := f.techprofile.GetTPInstance(ctx, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000713 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000714 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530715 log.Fields{
716 "path": tpPath,
717 "device-id": f.deviceHandler.device.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700718 techProfileInstance, err = f.techprofile.CreateTechProfileInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000719 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530720 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000721 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530722 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700723 "err": err,
Shrey Baid26912972020-04-16 21:02:31 +0530724 "tp-id": TpID,
725 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000726 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530727 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400728 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700729 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400730 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530731 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000732 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530733 log.Fields{
734 "uni": uni,
735 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530736 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530737 }
Gamze Abakafee36392019-10-03 11:17:24 +0000738
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700739 switch tpInst := techProfileInstance.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700740 case *tp_pb.TechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700741 if UsMeterID != 0 {
742 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
743 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
744 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000745 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700746 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700747 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700748 "onu-id": onuID,
749 "uni-id": uniID,
750 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700751 "meter-id": UsMeterID,
752 "device-id": f.deviceHandler.device.Id})
753 return 0, nil, nil
754 }
755 }
756 if DsMeterID != 0 {
757 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
758 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
759 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000760 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700761 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700762 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700763 "onu-id": onuID,
764 "uni-id": uniID,
765 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700766 "meter-id": DsMeterID,
767 "device-id": f.deviceHandler.device.Id})
768 return 0, nil, nil
769 }
770 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700771 allocID := tpInst.UsScheduler.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700772 for _, gem := range tpInst.UpstreamGemPortAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700773 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700774 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700775 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000776
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700777 if tpInstanceExists {
778 return allocID, gemPortIDs, techProfileInstance
779 }
780
781 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700782 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700783 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000784 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700785 log.Fields{
Matteo Scandolo84585372021-03-18 14:21:22 -0700786 "intf-id": intfID,
787 "onu-id": onuID,
788 "uni-id": uniID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700789 "alloc-ids": allocIDs,
790 "gemports": allgemPortIDs,
791 "device-id": f.deviceHandler.device.Id})
792 // Send Tconts and GEM ports to KV store
793 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530794 return allocID, gemPortIDs, techProfileInstance
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700795 case *openoltpb2.EponTechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700796 // CreateSchedulerQueues for EPON needs to be implemented here
797 // when voltha-protos for EPON is completed.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700798 allocID := tpInst.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700799 for _, gem := range tpInst.UpstreamQueueAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700800 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700801 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700802 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700803
804 if tpInstanceExists {
805 return allocID, gemPortIDs, techProfileInstance
806 }
807
808 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700809 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700810 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000811 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700812 log.Fields{
813 "alloc-ids": allocIDs,
814 "gemports": allgemPortIDs,
815 "device-id": f.deviceHandler.device.Id})
816 // Send Tconts and GEM ports to KV store
817 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
818 return allocID, gemPortIDs, techProfileInstance
819 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000820 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700821 log.Fields{
822 "tpInst": tpInst})
823 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530824 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530825}
826
npujarec5762e2020-01-01 14:08:48 +0530827func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530828
Neha Sharma96b7bf22020-06-15 10:37:32 +0000829 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530830 log.Fields{
831 "intf-id": intfID,
832 "onu-id": onuID,
833 "uni-id": uniID,
834 "alloc-id": allocID,
835 "gemport-ids": gemPortIDs,
836 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530837 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530838 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000839 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 +0530840 }
npujarec5762e2020-01-01 14:08:48 +0530841 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000842 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 +0530843 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700844
Neha Sharma96b7bf22020-06-15 10:37:32 +0000845 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 -0400846 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530847 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400848 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530849}
850
Neha Sharma96b7bf22020-06-15 10:37:32 +0000851func (f *OpenOltFlowMgr) populateTechProfilePerPonPort(ctx context.Context) error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000852 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530853 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000854 for _, intfID := range techRange.IntfIds {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700855 f.techprofile = f.resourceMgr.PonRsrMgr.TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400856 tpCount++
Neha Sharma96b7bf22020-06-15 10:37:32 +0000857 logger.Debugw(ctx, "init-tech-profile-done",
Shrey Baid26912972020-04-16 21:02:31 +0530858 log.Fields{
859 "intf-id": intfID,
860 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530861 }
862 }
863 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400864 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530865 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530866 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800867 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530868 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
869 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530870 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000871 logger.Infow(ctx, "populated-techprofile-for-ponports-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530872 log.Fields{
873 "numofTech": tpCount,
874 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
875 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530876 return nil
877}
878
Gamze Abaka7650be62021-02-26 10:50:36 +0000879func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
880 flowContext.classifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000881 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530882 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000883 "uplinkClassifier": flowContext.classifier,
884 "uplinkAction": flowContext.action})
885 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
Manikkaraj k884c1242019-04-11 16:26:42 +0530886 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530887}
888
Gamze Abaka7650be62021-02-26 10:50:36 +0000889func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
890 downlinkClassifier := flowContext.classifier
891 downlinkAction := flowContext.action
892
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700893 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000894 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530895 log.Fields{
896 "downlinkClassifier": downlinkClassifier,
897 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400898 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
899 if vlan, exists := downlinkClassifier[VlanVid]; exists {
900 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700901 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Gamze Abaka7650be62021-02-26 10:50:36 +0000902 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, flowContext.intfID, flowContext.onuID, flowContext.uniID) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000903 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530904 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000905 "flow": flowContext.logicalFlow,
Shrey Baid26912972020-04-16 21:02:31 +0530906 "device-id": f.deviceHandler.device.Id,
Gamze Abaka7650be62021-02-26 10:50:36 +0000907 "onu-id": flowContext.onuID,
908 "intf-id": flowContext.intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800909 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400910 }
911 }
912 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530913 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400914
Manikkaraj k884c1242019-04-11 16:26:42 +0530915 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700916 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400917 // vlan_vid is a uint32. must be type asserted as such or conversion fails
918 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530919 if ok {
920 downlinkAction[VlanVid] = dlClVid & 0xfff
921 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530922 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530923 "reason": "failed-to-convert-vlanid-classifier",
924 "vlan-id": VlanVid,
925 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530926 }
927
Gamze Abaka7650be62021-02-26 10:50:36 +0000928 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +0530929}
930
Gamze Abaka7650be62021-02-26 10:50:36 +0000931func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700932
Gamze Abaka7650be62021-02-26 10:50:36 +0000933 intfID := flowContext.intfID
934 onuID := flowContext.onuID
935 uniID := flowContext.uniID
936 classifier := flowContext.classifier
937 action := flowContext.action
938 allocID := flowContext.allocID
939 gemPortID := flowContext.gemPortID
940 tpID := flowContext.tpID
941 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +0000942 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530943 log.Fields{
944 "intf-id": intfID,
945 "onu-id": onuID,
946 "uni-id": uniID,
947 "device-id": f.deviceHandler.device.Id,
948 "classifier": classifier,
949 "action": action,
950 "direction": direction,
951 "alloc-id": allocID,
952 "gemport-id": gemPortID,
953 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700954
955 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000956 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +0530957 log.Fields{
958 "device-id": f.deviceHandler.device.Id,
959 "intf-id": intfID,
960 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800961 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530962 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800963 classifierProto, err := makeOpenOltClassifierField(classifier)
964 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530965 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530966 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000967 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +0530968 log.Fields{
969 "classifier": *classifierProto,
970 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +0000971 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800972 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530973 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530974 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000975 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +0530976 log.Fields{
977 "action": *actionProto,
978 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +0000979 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530980 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530981 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800982 log.Fields{
983 "classifier": classifier,
984 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +0530985 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800986 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530987 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700988
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700989 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700990 OnuId: int32(onuID),
991 UniId: int32(uniID),
992 FlowId: logicalFlow.Id,
993 FlowType: direction,
994 AllocId: int32(allocID),
995 NetworkIntfId: int32(networkIntfID),
996 GemportId: int32(gemPortID),
997 Classifier: classifierProto,
998 Action: actionProto,
999 Priority: int32(logicalFlow.Priority),
1000 Cookie: logicalFlow.Cookie,
1001 PortNo: flowContext.portNo,
1002 TechProfileId: tpID,
1003 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1004 PbitToGemport: flowContext.pbitToGem,
1005 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001006 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001007 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001008 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301009 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001010 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301011 log.Fields{"direction": direction,
1012 "device-id": f.deviceHandler.device.Id,
1013 "flow": flow,
1014 "intf-id": intfID,
1015 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001016
David K. Bainbridge794735f2020-02-11 21:01:37 -08001017 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301018}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001019
Gamze Abaka7650be62021-02-26 10:50:36 +00001020func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1021
1022 intfID := flowContext.intfID
1023 onuID := flowContext.onuID
1024 uniID := flowContext.uniID
1025 logicalFlow := flowContext.logicalFlow
1026 classifier := flowContext.classifier
1027 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301028
Neha Sharma96b7bf22020-06-15 10:37:32 +00001029 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301030 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301031 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001032 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301033 "action": action,
1034 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001035 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301036 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301037
1038 // Clear the action map
1039 for k := range action {
1040 delete(action, k)
1041 }
1042
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001043 action[TrapToHost] = true
1044 classifier[UDPSrc] = uint32(68)
1045 classifier[UDPDst] = uint32(67)
1046 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301047
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001048 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001049 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301050 log.Fields{
1051 "device-id": f.deviceHandler.device.Id,
1052 "intf-id": intfID,
1053 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001054 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301055 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301056
Neha Sharma96b7bf22020-06-15 10:37:32 +00001057 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301058 log.Fields{
1059 "ul_classifier": classifier,
1060 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001061 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301062 "intf-id": intfID,
1063 "onu-id": onuID,
1064 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301065
David K. Bainbridge794735f2020-02-11 21:01:37 -08001066 classifierProto, err := makeOpenOltClassifierField(classifier)
1067 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301068 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301069 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001070 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001071 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001072 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301073 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301074 }
1075
David K. Bainbridge794735f2020-02-11 21:01:37 -08001076 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001077 OnuId: int32(onuID),
1078 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001079 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001080 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001081 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001082 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001083 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301084 Classifier: classifierProto,
1085 Action: actionProto,
1086 Priority: int32(logicalFlow.Priority),
1087 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001088 PortNo: flowContext.portNo,
1089 TechProfileId: flowContext.tpID,
1090 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1091 PbitToGemport: flowContext.pbitToGem,
1092 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001093 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001094 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001095 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001096 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001097 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301098 log.Fields{
1099 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001100 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301101 "intf-id": intfID,
1102 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301103
David K. Bainbridge794735f2020-02-11 21:01:37 -08001104 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301105}
1106
Esin Karamanae41e2b2019-12-17 18:13:13 +00001107//addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001108func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1109 delete(flowContext.classifier, VlanVid)
1110 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001111}
1112
1113//addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001114func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1115
1116 intfID := flowContext.intfID
1117 onuID := flowContext.onuID
1118 uniID := flowContext.uniID
1119 logicalFlow := flowContext.logicalFlow
1120 classifier := flowContext.classifier
1121 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001122
Neha Sharma96b7bf22020-06-15 10:37:32 +00001123 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001124 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301125 return olterrors.NewErrNotFound("nni-interface-id",
1126 log.Fields{
1127 "classifier": classifier,
1128 "action": action,
1129 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001130 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001131 }
1132
1133 // Clear the action map
1134 for k := range action {
1135 delete(action, k)
1136 }
1137
1138 action[TrapToHost] = true
1139 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001140
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001141 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001142 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001143 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001144 }
1145
Neha Sharma96b7bf22020-06-15 10:37:32 +00001146 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301147 log.Fields{
1148 "ul_classifier": classifier,
1149 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001150 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301151 "device-id": f.deviceHandler.device.Id,
1152 "intf-id": intfID,
1153 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001154
David K. Bainbridge794735f2020-02-11 21:01:37 -08001155 classifierProto, err := makeOpenOltClassifierField(classifier)
1156 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301157 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001158 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001159 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301160 log.Fields{
1161 "classifier": *classifierProto,
1162 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001163 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001164 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301165 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001166 }
1167
David K. Bainbridge794735f2020-02-11 21:01:37 -08001168 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001169 OnuId: int32(onuID),
1170 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001171 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001172 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001173 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001174 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001175 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001176 Classifier: classifierProto,
1177 Action: actionProto,
1178 Priority: int32(logicalFlow.Priority),
1179 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001180 PortNo: flowContext.portNo,
1181 TechProfileId: flowContext.tpID,
1182 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1183 PbitToGemport: flowContext.pbitToGem,
1184 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001185 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001186
David K. Bainbridge794735f2020-02-11 21:01:37 -08001187 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001188 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 -08001189 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001190
David K. Bainbridge794735f2020-02-11 21:01:37 -08001191 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001192}
1193
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001194// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001195func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1196 intfID := flowContext.intfID
1197 onuID := flowContext.onuID
1198 uniID := flowContext.uniID
1199 portNo := flowContext.portNo
1200 allocID := flowContext.allocID
1201 gemPortID := flowContext.gemPortID
1202 logicalFlow := flowContext.logicalFlow
1203 classifier := flowContext.classifier
1204 action := flowContext.action
1205
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001206 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301207 log.Fields{
1208 "intf-id": intfID,
1209 "onu-id": onuID,
1210 "port-no": portNo,
1211 "alloc-id": allocID,
1212 "gemport-id": gemPortID,
1213 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001214 "flow": logicalFlow,
1215 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301216
1217 uplinkClassifier := make(map[string]interface{})
1218 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301219
manikkaraj kbf256be2019-03-25 00:13:48 +05301220 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001221 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001222 uplinkClassifier[PacketTagType] = SingleTag
1223 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001224 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301225 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001226 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001227 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001228 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301229 "device-id": f.deviceHandler.device.Id,
1230 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001231 "intf-id": intfID,
1232 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001233 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301234 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001235 //Add Uplink EthType Flow
1236 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301237 log.Fields{
1238 "ul_classifier": uplinkClassifier,
1239 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001240 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301241 "device-id": f.deviceHandler.device.Id,
1242 "intf-id": intfID,
1243 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301244
David K. Bainbridge794735f2020-02-11 21:01:37 -08001245 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1246 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301247 return olterrors.NewErrInvalidValue(log.Fields{
1248 "classifier": uplinkClassifier,
1249 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301250 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001251 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301252 log.Fields{
1253 "classifier": *classifierProto,
1254 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001255 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001256 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301257 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301258 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001259 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301260 log.Fields{
1261 "action": *actionProto,
1262 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001263 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301264 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301265 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001266 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301267 "action": action,
1268 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001269 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301270 }
1271
David K. Bainbridge794735f2020-02-11 21:01:37 -08001272 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001273 OnuId: int32(onuID),
1274 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001275 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001276 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001277 AllocId: int32(allocID),
1278 NetworkIntfId: int32(networkIntfID),
1279 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301280 Classifier: classifierProto,
1281 Action: actionProto,
1282 Priority: int32(logicalFlow.Priority),
1283 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001284 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001285 TechProfileId: flowContext.tpID,
1286 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1287 PbitToGemport: flowContext.pbitToGem,
1288 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001289 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001290 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001291 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001292 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001293 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301294 log.Fields{
1295 "device-id": f.deviceHandler.device.Id,
1296 "onu-id": onuID,
1297 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001298 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301299 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001300
David K. Bainbridge794735f2020-02-11 21:01:37 -08001301 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301302}
1303
David K. Bainbridge794735f2020-02-11 21:01:37 -08001304func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001305 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001306
1307 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1308 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1309 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001310 if vlanID != ReservedVlan {
1311 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001312 classifier.OVid = vid
1313 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301314 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001315 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1316 vid := uint32(metadata)
1317 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001318 classifier.IVid = vid
1319 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301320 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301321 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001322 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301323 classifier.OPbits = vlanPcp
1324 } else {
1325 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301326 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001327 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1328 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1329 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1330 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001331 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001332 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1333 classifier.PktTagType = pktTagType
1334
1335 switch pktTagType {
1336 case SingleTag:
1337 case DoubleTag:
1338 case Untagged:
1339 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001340 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301341 }
1342 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001343 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301344}
1345
Gamze Abaka724d0852020-03-18 12:10:24 +00001346func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001347 var actionCmd openoltpb2.ActionCmd
1348 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301349 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001350 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301351 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001352 if _, ok := actionInfo[VlanPcp]; ok {
1353 action.Cmd.RemarkInnerPbits = true
1354 action.IPbits = actionInfo[VlanPcp].(uint32)
1355 if _, ok := actionInfo[VlanVid]; ok {
1356 action.Cmd.TranslateInnerTag = true
1357 action.IVid = actionInfo[VlanVid].(uint32)
1358 }
1359 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001360 } else if _, ok := actionInfo[PushVlan]; ok {
1361 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301362 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001363 if _, ok := actionInfo[VlanPcp]; ok {
1364 action.OPbits = actionInfo[VlanPcp].(uint32)
1365 action.Cmd.RemarkOuterPbits = true
1366 if _, ok := classifierInfo[VlanVid]; ok {
1367 action.IVid = classifierInfo[VlanVid].(uint32)
1368 action.Cmd.TranslateInnerTag = true
1369 }
1370 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001371 } else if _, ok := actionInfo[TrapToHost]; ok {
1372 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301373 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001374 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301375 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001376 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301377}
1378
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001379// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001380func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001381 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301382}
1383
Gamze Abakafee36392019-10-03 11:17:24 +00001384// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001385func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301386 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001387 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1388
Gamze Abakafee36392019-10-03 11:17:24 +00001389 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301390 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001391 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301392 // return err
1393 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001394 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001395 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 +00001396 }
1397 return nil
1398}
1399
1400// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301401func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001402 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001403 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001404 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001405 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301406 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1407 log.Fields{
1408 "tp-id": tpID,
1409 "uni-port-name": uniPortName,
1410 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001411 }
1412 return nil
1413}
1414
David K. Bainbridge794735f2020-02-11 21:01:37 -08001415func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001416
1417 var intfID uint32
1418 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1419 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1420 */
1421 if deviceFlow.AccessIntfId != -1 {
1422 intfID = uint32(deviceFlow.AccessIntfId)
1423 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001424 // We need to log the valid interface ID.
1425 // 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 +00001426 intfID = uint32(deviceFlow.NetworkIntfId)
1427 }
1428
Neha Sharma96b7bf22020-06-15 10:37:32 +00001429 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301430 "flow": *deviceFlow,
1431 "device-id": f.deviceHandler.device.Id,
1432 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001433 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001434
1435 st, _ := status.FromError(err)
1436 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001437 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001438 "err": err,
1439 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301440 "device-id": f.deviceHandler.device.Id,
1441 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001442 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301443 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001444
1445 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001446 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301447 log.Fields{"err": err,
1448 "device-flow": deviceFlow,
1449 "device-id": f.deviceHandler.device.Id,
1450 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001451 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001452 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001453 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301454 log.Fields{
1455 "flow": *deviceFlow,
1456 "device-id": f.deviceHandler.device.Id,
1457 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001458
1459 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1460 if deviceFlow.AccessIntfId != -1 {
1461 // No need to register the flow if it is a trap on nni flow.
1462 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1463 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1464 return err
1465 }
1466 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001467 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001468}
1469
Neha Sharma96b7bf22020-06-15 10:37:32 +00001470func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1471 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301472 log.Fields{
1473 "flow": *deviceFlow,
1474 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001475 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001476 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001477 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001478 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301479 log.Fields{
1480 "err": err,
1481 "deviceFlow": deviceFlow,
1482 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001483 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001484 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001485 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001486 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001487
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001488 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001489 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001490 "of-flow-id": ofFlowID,
1491 "flow": *deviceFlow,
1492 "device-id": f.deviceHandler.device.Id,
1493 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001494 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301495}
1496
David K. Bainbridge794735f2020-02-11 21:01:37 -08001497func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001498
1499 classifierInfo := make(map[string]interface{})
1500 actionInfo := make(map[string]interface{})
1501
1502 classifierInfo[EthType] = uint32(LldpEthType)
1503 classifierInfo[PacketTagType] = Untagged
1504 actionInfo[TrapToHost] = true
1505
1506 // LLDP flow is installed to trap LLDP packets on the NNI port.
1507 // We manage flow_id resource pool on per PON port basis.
1508 // Since this situation is tricky, as a hack, we pass the NNI port
1509 // index (network_intf_id) as PON port Index for the flow_id resource
1510 // pool. Also, there is no ONU Id available for trapping LLDP packets
1511 // on NNI port, use onu_id as -1 (invalid)
1512 // ****************** CAVEAT *******************
1513 // This logic works if the NNI Port Id falls within the same valid
1514 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1515 // we need to have a re-look at this.
1516 // *********************************************
1517
1518 var onuID = -1
1519 var uniID = -1
1520 var gemPortID = -1
1521
Neha Sharma96b7bf22020-06-15 10:37:32 +00001522 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001523 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301524 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001525 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001526 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001527 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001528 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001529 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001530
David K. Bainbridge794735f2020-02-11 21:01:37 -08001531 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1532 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301533 return olterrors.NewErrInvalidValue(
1534 log.Fields{
1535 "classifier": classifierInfo,
1536 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001537 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001538 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301539 log.Fields{
1540 "classifier": *classifierProto,
1541 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001542 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001543 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301544 return olterrors.NewErrInvalidValue(
1545 log.Fields{
1546 "action": actionInfo,
1547 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001548 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001549 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301550 log.Fields{
1551 "action": *actionProto,
1552 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001553
1554 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1555 OnuId: int32(onuID), // OnuId not required
1556 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001557 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001558 FlowType: Downstream,
1559 NetworkIntfId: int32(networkInterfaceID),
1560 GemportId: int32(gemPortID),
1561 Classifier: classifierProto,
1562 Action: actionProto,
1563 Priority: int32(flow.Priority),
1564 Cookie: flow.Cookie,
1565 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001566 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001567 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301568 log.Fields{
1569 "flow": downstreamflow,
1570 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001571 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001572 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301573 log.Fields{
1574 "device-id": f.deviceHandler.device.Id,
1575 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001576 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001577
David K. Bainbridge794735f2020-02-11 21:01:37 -08001578 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301579}
1580
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001581func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1582 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001583}
1584
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001585//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001586func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001587 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1588 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1589 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001590 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301591 log.Fields{
1592 "intf-id": intfID,
1593 "onu-id": onuID,
1594 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001595 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001596 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301597 return nil, olterrors.NewErrNotFound("onu-child-device",
1598 log.Fields{
1599 "onu-id": onuID,
1600 "intf-id": intfID,
1601 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001602 }
1603 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1604 //better to ad the device to cache here.
1605 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1606 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001607 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301608 log.Fields{
1609 "intf-id": intfID,
1610 "onu-id": onuID,
1611 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001612 }
1613
1614 return onuDev.(*OnuDevice), nil
1615}
1616
1617//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001618func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1619 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301620 log.Fields{
1621 "pon-port": intfID,
1622 "onu-id": onuID,
1623 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001624 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001625 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001626 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301627 return nil, olterrors.NewErrNotFound("onu",
1628 log.Fields{
1629 "interface-id": parentPortNo,
1630 "onu-id": onuID,
1631 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001632 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301633 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001634 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301635 log.Fields{
1636 "device-id": f.deviceHandler.device.Id,
1637 "child_device_id": onuDevice.Id,
1638 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301639 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301640}
1641
Neha Sharma96b7bf22020-06-15 10:37:32 +00001642func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1643 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301644 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001645 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301646 log.Fields{
1647 "intf-id": intfID,
1648 "onu-id": onuID,
1649 "uni-id": uniID,
1650 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001651 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301652 }
1653
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001654 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpInstancePath: tpPath, GemPortId: gemPortID}
1655 logger.Infow(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301656 log.Fields{
1657 "msg": *delGemPortMsg,
1658 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001659 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301660 delGemPortMsg,
1661 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001662 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001663 onuDev.deviceType,
1664 onuDev.deviceID,
1665 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301666 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1667 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001668 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301669 "to-adapter": onuDev.deviceType,
1670 "onu-id": onuDev.deviceID,
1671 "proxyDeviceID": onuDev.proxyDeviceID,
1672 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301673 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001674 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301675 log.Fields{
1676 "msg": delGemPortMsg,
1677 "from-adapter": f.deviceHandler.device.Type,
1678 "to-adapter": onuDev.deviceType,
1679 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301680 return nil
1681}
1682
Neha Sharma96b7bf22020-06-15 10:37:32 +00001683func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1684 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301685 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001686 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301687 log.Fields{
1688 "intf-id": intfID,
1689 "onu-id": onuID,
1690 "uni-id": uniID,
1691 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001692 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301693 }
1694
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001695 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpInstancePath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001696 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301697 log.Fields{
1698 "msg": *delTcontMsg,
1699 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001700 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301701 delTcontMsg,
1702 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001703 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001704 onuDev.deviceType,
1705 onuDev.deviceID,
1706 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301707 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1708 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001709 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301710 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1711 "proxyDeviceID": onuDev.proxyDeviceID,
1712 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301713 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001714 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301715 log.Fields{
1716 "msg": delTcontMsg,
1717 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301718 return nil
1719}
1720
Girish Gowdrac3037402020-01-22 20:29:53 +05301721// Once the gemport is released for a given onu, it also has to be cleared from local cache
1722// which was used for deriving the gemport->logicalPortNo during packet-in.
1723// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1724// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001725func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001726 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301727 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001728 "gem-port-id": gemPortID,
1729 "intf-id": intfID,
1730 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001731 "device-id": f.deviceHandler.device.Id})
1732 f.onuGemInfoLock.RLock()
1733 onugem, ok := f.onuGemInfoMap[onuID]
1734 f.onuGemInfoLock.RUnlock()
1735 if !ok {
1736 logger.Warnw(ctx, "onu gem info already cleared from cache", log.Fields{
1737 "gem-port-id": gemPortID,
1738 "intf-id": intfID,
1739 "onu-id": onuID,
1740 "device-id": f.deviceHandler.device.Id})
1741 return
1742 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001743deleteLoop:
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001744 for j, gem := range onugem.GemPorts {
1745 // If the gemport is found, delete it from local cache.
1746 if gem == gemPortID {
1747 onugem.GemPorts = append(onugem.GemPorts[:j], onugem.GemPorts[j+1:]...)
1748 f.onuGemInfoLock.Lock()
1749 f.onuGemInfoMap[onuID] = onugem
1750 f.onuGemInfoLock.Unlock()
1751 logger.Infow(ctx, "removed-gemport-from-local-cache",
1752 log.Fields{
1753 "intf-id": intfID,
1754 "onu-id": onuID,
1755 "deletedgemport-id": gemPortID,
1756 "gemports": onugem.GemPorts,
1757 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001758 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301759 }
1760 }
1761}
1762
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301763//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001764// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001765func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Girish Gowdra82c80982021-03-26 16:22:02 -07001766 gemPortID int32, flowID uint64, portNum uint32, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001767
Girish Gowdraa482f272021-03-24 23:04:19 -07001768 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
1769 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001770 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1771 log.Fields{
1772 "tpPath": tpPath,
1773 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001774
1775 used := f.isGemPortUsedByAnotherFlow(uint32(gemPortID))
1776
1777 if used {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001778 f.gemToFlowIDsKey.RLock()
1779 flowIDs := f.gemToFlowIDs[uint32(gemPortID)]
1780 f.gemToFlowIDsKey.RUnlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001781
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001782 for i, flowIDinMap := range flowIDs {
1783 if flowIDinMap == flowID {
1784 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001785 f.gemToFlowIDsKey.Lock()
1786 f.gemToFlowIDs[uint32(gemPortID)] = flowIDs
1787 f.gemToFlowIDsKey.Unlock()
1788 // everytime gemToFlowIDs cache is updated the same should be updated
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001789 // in kv store by calling UpdateFlowIDsForGem
Girish Gowdraa482f272021-03-24 23:04:19 -07001790 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, intfID, uint32(gemPortID), flowIDs); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001791 return err
1792 }
1793 break
1794 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001795 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001796 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1797 log.Fields{
1798 "gemport-id": gemPortID,
1799 "usedByFlows": flowIDs,
1800 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -07001801
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001802 return nil
1803 }
1804 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 -07001805 f.deleteGemPortFromLocalCache(ctx, intfID, uint32(onuID), uint32(gemPortID))
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001806 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, intfID, uint32(onuID), uint32(gemPortID)) // ignore error and proceed.
1807 //everytime an entry is deleted from gemToFlowIDs cache, the same should be updated in kv as well
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001808 // by calling DeleteFlowIDsForGem
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001809 f.gemToFlowIDsKey.Lock()
1810 delete(f.gemToFlowIDs, uint32(gemPortID))
1811 f.gemToFlowIDsKey.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001812
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001813 f.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, uint32(gemPortID))
1814
1815 f.resourceMgr.FreeGemPortID(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001816
Mahir Gunyel1d20eff2021-07-04 15:39:36 -07001817 //First remove TCONT from child if needed. Then remove the GEM.
1818 //It is expected from child to clean ani side conf if all GEMs of TP are deleted.
1819 //Before this, ensure that the related TCONT deletions are informed to child.
1820 //Refer to VOL-4215.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001821 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1822 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1823 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1824 log.Fields{
1825 "tp-id": tpID,
1826 "path": tpPath}, err)
1827 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001828 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001829 case *tp_pb.TechProfileInstance:
Gamze Abakacb0e6772021-06-10 08:32:12 +00001830 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst, uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001831 if !ok {
Girish Gowdraa482f272021-03-24 23:04:19 -07001832 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001833 logger.Warn(ctx, err)
1834 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001835 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001836 logger.Warn(ctx, err)
1837 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001838 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 -07001839 logger.Warn(ctx, err)
1840 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001841 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 -07001842 logger.Warn(ctx, err)
1843 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001844 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001845 case *tp_pb.EponTechProfileInstance:
Girish Gowdraa482f272021-03-24 23:04:19 -07001846 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001847 logger.Warn(ctx, err)
1848 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001849 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001850 logger.Warn(ctx, err)
1851 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001852 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001853 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001854 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001855 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05301856 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07001857 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05301858 "onu-id": onuID,
1859 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001860 "device-id": f.deviceHandler.device.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001861 "alloc-id": techprofileInst.AllocId})
Gamze Abakafee36392019-10-03 11:17:24 +00001862 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001863 default:
1864 logger.Errorw(ctx, "error-unknown-tech",
1865 log.Fields{
1866 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001867 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001868
Mahir Gunyel1d20eff2021-07-04 15:39:36 -07001869 // Delete the gem port on the ONU. Send Gem Removal After TCONT removal.
1870 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
1871 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
1872 log.Fields{
1873 "err": err,
1874 "intfID": intfID,
1875 "onu-id": onuID,
1876 "uni-id": uniID,
1877 "device-id": f.deviceHandler.device.Id,
1878 "gemport-id": gemPortID})
1879 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301880 return nil
1881}
1882
David K. Bainbridge794735f2020-02-11 21:01:37 -08001883// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07001884func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001885 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05301886 log.Fields{
1887 "flowDirection": flowDirection,
1888 "flow": *flow,
1889 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001890
1891 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001892 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00001893 }
1894
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301895 classifierInfo := make(map[string]interface{})
1896
Neha Sharma96b7bf22020-06-15 10:37:32 +00001897 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301898 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001899 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001900 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301901 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301902
David K. Bainbridge794735f2020-02-11 21:01:37 -08001903 onuID := int32(onu)
1904 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001905 tpID, err := getTpIDFromFlow(ctx, flow)
1906 if err != nil {
1907 return olterrors.NewErrNotFound("tp-id",
1908 log.Fields{
1909 "flow": flow,
1910 "intf-id": Intf,
1911 "onu-id": onuID,
1912 "uni-id": uniID,
1913 "device-id": f.deviceHandler.device.Id}, err)
1914 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301915
1916 for _, field := range flows.GetOfbFields(flow) {
1917 if field.Type == flows.IP_PROTO {
1918 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00001919 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301920 }
1921 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001922 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05301923 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001924 "flow-id": flow.Id,
1925 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05301926 "onu-id": onuID,
1927 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301928
1929 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1930 onuID = -1
1931 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00001932 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
1933 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001934 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001935 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001936 log.Fields{
1937 "port-number": inPort,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001938 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001939 return err
David K. Bainbridge794735f2020-02-11 21:01:37 -08001940 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301941 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001942
1943 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
1944 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001945 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
1946 return err
1947 }
Girish Gowdra82c80982021-03-26 16:22:02 -07001948
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001949 f.flowIDToGemsLock.Lock()
1950 gems, ok := f.flowIDToGems[flow.Id]
1951 if !ok {
1952 logger.Errorw(ctx, "flow-id-to-gem-map-not-found", log.Fields{"flowID": flow.Id})
1953 f.flowIDToGemsLock.Unlock()
1954 return olterrors.NewErrNotFound("flow-id-to-gem-map-not-found", log.Fields{"flowID": flow.Id}, nil)
1955 }
1956 copyOfGems := make([]uint32, len(gems))
1957 _ = copy(copyOfGems, gems)
1958 // Delete the flow-id to gemport list entry from the map now the flow is deleted.
1959 delete(f.flowIDToGems, flow.Id)
1960 f.flowIDToGemsLock.Unlock()
1961
1962 logger.Debugw(ctx, "gems-to-be-cleared", log.Fields{"gems": copyOfGems})
1963 for _, gem := range copyOfGems {
1964 if err = f.clearResources(ctx, Intf, onuID, uniID, int32(gem), flow.Id, portNum, tpID); err != nil {
Girish Gowdra0aca4982021-01-04 12:44:27 -08001965 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001966 "flow-id": flow.Id,
1967 "device-id": f.deviceHandler.device.Id,
1968 "onu-id": onuID,
1969 "intf": Intf,
1970 "gem": gem,
1971 "err": err,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001972 })
1973 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301974 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301975 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001976
Girish Gowdra82c80982021-03-26 16:22:02 -07001977 // Decrement reference count for the meter associated with the given <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
1978 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, Intf, uint32(onuID), uint32(uniID), tpID, false); err != nil {
1979 return err
1980 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001981 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001982}
1983
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001984//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07001985func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001986
Matteo Scandolof16389e2021-05-18 00:47:08 +00001987 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301988 var direction string
1989 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001990
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301991 for _, action := range flows.GetActions(flow) {
1992 if action.Type == flows.OUTPUT {
1993 if out := action.GetOutput(); out != nil {
1994 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00001995 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301996 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001997 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07001998 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001999 }
2000 }
2001 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002002
2003 if flows.HasGroup(flow) {
2004 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002005 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Esin Karamanccb714b2019-11-29 15:02:06 +00002006 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302007 direction = Upstream
2008 } else {
2009 direction = Downstream
2010 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302011
Girish Gowdracefae192020-03-19 18:14:10 -07002012 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002013 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002014
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002015 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002016}
2017
Esin Karamanae41e2b2019-12-17 18:13:13 +00002018//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2019func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2020 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2021 if ethType, ok := classifierInfo[EthType]; ok {
2022 if ethType.(uint32) == IPv4EthType {
2023 if ipProto, ok := classifierInfo[IPProto]; ok {
2024 if ipProto.(uint32) == IgmpProto {
2025 return true
2026 }
2027 }
2028 }
2029 }
2030 }
2031 return false
2032}
2033
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002034// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
2035func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *voltha.OfpFlowStats, addFlow bool, flowMetadata *voltha.FlowMetadata) error {
2036 // Step1 : Fill flowControlBlock
2037 // Step2 : Push the flowControlBlock to ONU channel
2038 // Step3 : Wait on response channel for response
2039 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002040 startTime := time.Now()
2041 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002042 errChan := make(chan error)
2043 flowCb := flowControlBlock{
2044 ctx: ctx,
2045 addFlow: addFlow,
2046 flow: flow,
2047 flowMetadata: flowMetadata,
2048 errChan: &errChan,
2049 }
2050 inPort, outPort := getPorts(flow)
2051 var onuID uint32
2052 if inPort != InvalidPort && outPort != InvalidPort {
2053 _, _, onuID, _ = ExtractAccessFromFlow(inPort, outPort)
2054 }
2055 // inPort or outPort is InvalidPort for trap-from-nni flows.
2056 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2057 // Send the flowCb on the ONU flow channel
2058 f.incomingFlows[onuID] <- flowCb
2059 // Wait on the channel for flow handlers return value
2060 err := <-errChan
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002061 logger.Infow(ctx, "process-flow--received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002062 return err
2063}
2064
2065// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2066// Each incoming flow is processed in a synchronous manner, i.e., the flow is processed to completion before picking another
2067func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(subscriberFlowChannel chan flowControlBlock) {
2068 for {
2069 // block on the channel to receive an incoming flow
2070 // process the flow completely before proceeding to handle the next flow
2071 flowCb := <-subscriberFlowChannel
2072 if flowCb.addFlow {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002073 logger.Info(flowCb.ctx, "adding-flow-start")
2074 startTime := time.Now()
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002075 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002076 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002077 // Pass the return value over the return channel
2078 *flowCb.errChan <- err
2079 } else {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002080 logger.Info(flowCb.ctx, "removing-flow-start")
2081 startTime := time.Now()
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002082 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002083 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002084 // Pass the return value over the return channel
2085 *flowCb.errChan <- err
2086 }
2087 }
2088}
2089
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002090// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302091// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002092func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002093 classifierInfo := make(map[string]interface{})
2094 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002095 var UsMeterID uint32
2096 var DsMeterID uint32
2097
Neha Sharma96b7bf22020-06-15 10:37:32 +00002098 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302099 log.Fields{
2100 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002101 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002102 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002103
Neha Sharma96b7bf22020-06-15 10:37:32 +00002104 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002105 if err != nil {
2106 // Error logging is already done in the called function
2107 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002108 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302109 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002110
Esin Karamanccb714b2019-11-29 15:02:06 +00002111 if flows.HasGroup(flow) {
2112 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002113 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002114 }
2115
manikkaraj k17652a72019-05-06 09:06:36 -04002116 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002117 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002118 if err != nil {
2119 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002120 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002121 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002122
Neha Sharma96b7bf22020-06-15 10:37:32 +00002123 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302124 log.Fields{
2125 "classifierinfo_inport": classifierInfo[InPort],
2126 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002127 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002128
Humera Kouser94d7a842019-08-25 19:04:32 -04002129 if ethType, ok := classifierInfo[EthType]; ok {
2130 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002131 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002132 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002133 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002134 if ethType.(uint32) == PPPoEDEthType {
2135 if voltha.Port_ETHERNET_NNI == IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
2136 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2137 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2138 }
2139 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002140 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002141 if ipProto, ok := classifierInfo[IPProto]; ok {
2142 if ipProto.(uint32) == IPProtoDhcp {
2143 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302144 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002145 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002146 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002147 }
2148 }
2149 }
2150 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002151 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002152 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002153 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002154 }
A R Karthick1f85b802019-10-11 05:06:05 +00002155
npujarec5762e2020-01-01 14:08:48 +05302156 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002157 // also update flowmgr cache
2158 f.onuGemInfoLock.Lock()
2159 onugem, ok := f.onuGemInfoMap[onuID]
2160 if ok {
2161 found := false
2162 for _, uni := range onugem.UniPorts {
2163 if uni == portNo {
2164 found = true
2165 break
2166 }
2167 }
2168 if !found {
2169 onugem.UniPorts = append(onugem.UniPorts, portNo)
2170 f.onuGemInfoMap[onuID] = onugem
2171 logger.Infow(ctx, "added uni port to onugem cache", log.Fields{"uni": portNo})
2172 }
2173 }
2174 f.onuGemInfoLock.Unlock()
A R Karthick1f85b802019-10-11 05:06:05 +00002175
Neha Sharma96b7bf22020-06-15 10:37:32 +00002176 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002177 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302178 return olterrors.NewErrNotFound("tpid-for-flow",
2179 log.Fields{
2180 "flow": flow,
2181 "intf-id": IntfID,
2182 "onu-id": onuID,
2183 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002184 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002185 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302186 log.Fields{
2187 "tp-id": TpID,
2188 "intf-id": intfID,
2189 "onu-id": onuID,
2190 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002191 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002192 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002193 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002194 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002195 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002196 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002197
2198 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002199 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002200}
Girish Gowdra3d633032019-12-10 16:37:05 +05302201
Esin Karamanccb714b2019-11-29 15:02:06 +00002202// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002203func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002204 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002205 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302206 "classifier-info": classifierInfo,
2207 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002208
Esin Karaman65409d82020-03-18 10:58:18 +00002209 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002210 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002211 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002212 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002213
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002214 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002215
David K. Bainbridge794735f2020-02-11 21:01:37 -08002216 onuID := NoneOnuID
2217 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002218
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002219 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002220 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002221 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002222 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002223 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2224 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002225 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002226 }
2227 groupID := actionInfo[GroupID].(uint32)
2228 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002229 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002230 FlowType: Multicast,
2231 NetworkIntfId: int32(networkInterfaceID),
2232 GroupId: groupID,
2233 Classifier: classifierProto,
2234 Priority: int32(flow.Priority),
2235 Cookie: flow.Cookie}
2236
Kent Hagermane6ff1012020-07-14 15:07:53 -04002237 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002238 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002239 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002240 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002241 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002242 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002243 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002244 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002245 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002246 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002247 //cached group can be removed now
2248 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002249 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002250 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002251 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002252
David K. Bainbridge794735f2020-02-11 21:01:37 -08002253 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002254}
2255
Esin Karaman65409d82020-03-18 10:58:18 +00002256//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2257func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2258 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002259 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002260 if err != nil {
2261 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2262 }
2263 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002264 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002265
2266 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2267 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002268}
2269
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002270//sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002271func (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 -07002272
Neha Sharma96b7bf22020-06-15 10:37:32 +00002273 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302274 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002275 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302276 log.Fields{
2277 "intf-id": intfID,
2278 "onu-id": onuID,
2279 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002280 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302281 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002282 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002283
Neha Sharma96b7bf22020-06-15 10:37:32 +00002284 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002285 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{
2286 UniId: uniID,
2287 TpInstancePath: tpPath,
2288 TechTpInstance: &ic.InterAdapterTechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
2289 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002290 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002291 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
manikkaraj k17652a72019-05-06 09:06:36 -04002292 tpDownloadMsg,
2293 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03002294 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002295 onuDev.deviceType,
2296 onuDev.deviceID,
2297 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002298 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302299 return olterrors.NewErrCommunication("send-techprofile-download-request",
2300 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03002301 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05302302 "to-adapter": onuDev.deviceType,
2303 "onu-id": onuDev.deviceID,
2304 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002305 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002306 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302307 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302308}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002309
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302310//UpdateOnuInfo function adds onu info to cache and kvstore
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002311//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002312func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302313
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002314 f.onuGemInfoLock.RLock()
2315 _, ok := f.onuGemInfoMap[onuID]
2316 f.onuGemInfoLock.RUnlock()
Girish Gowdra9602eb42020-09-09 15:50:39 -07002317 // If the ONU already exists in onuGemInfo list, nothing to do
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002318 if ok {
2319 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2320 log.Fields{"onuID": onuID,
2321 "serialNum": serialNum})
2322 return nil
Girish Gowdra9602eb42020-09-09 15:50:39 -07002323 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002324
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002325 onuGemInfo := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2326 f.onuGemInfoLock.Lock()
2327 f.onuGemInfoMap[onuID] = &onuGemInfo
2328 f.onuGemInfoLock.Unlock()
2329 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onuID, onuGemInfo); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002330 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302331 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002332 logger.Infow(ctx, "updated-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302333 log.Fields{
2334 "intf-id": intfID,
2335 "onu-id": onuID,
2336 "serial-num": serialNum,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002337 "onu": onuGemInfo,
Shrey Baid26912972020-04-16 21:02:31 +05302338 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002339 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002340}
2341
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302342//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302343func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002344
Neha Sharma96b7bf22020-06-15 10:37:32 +00002345 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302346 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002347 "gem-port-id": gemPort,
2348 "intf-id": intfID,
2349 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002350 "device-id": f.deviceHandler.device.Id})
2351 f.onuGemInfoLock.RLock()
2352 onugem, ok := f.onuGemInfoMap[onuID]
2353 f.onuGemInfoLock.RUnlock()
2354 if !ok {
2355 logger.Warnw(ctx, "onu gem info is missing", log.Fields{
2356 "gem-port-id": gemPort,
2357 "intf-id": intfID,
2358 "onu-id": onuID,
2359 "device-id": f.deviceHandler.device.Id})
2360 return
2361 }
2362
2363 if onugem.OnuID == onuID {
2364 // check if gem already exists , else update the cache and kvstore
2365 for _, gem := range onugem.GemPorts {
2366 if gem == gemPort {
2367 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
2368 log.Fields{
2369 "gem": gemPort,
2370 "device-id": f.deviceHandler.device.Id})
2371 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302372 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302373 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002374 onugem.GemPorts = append(onugem.GemPorts, gemPort)
2375 f.onuGemInfoLock.Lock()
2376 f.onuGemInfoMap[onuID] = onugem
2377 f.onuGemInfoLock.Unlock()
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002378 logger.Debugw(ctx, "updated onu gem info from cache", log.Fields{"onugem": onugem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002379 } else {
2380 logger.Warnw(ctx, "mismatched onu id", log.Fields{
2381 "gem-port-id": gemPort,
2382 "intf-id": intfID,
2383 "onu-id": onuID,
2384 "device-id": f.deviceHandler.device.Id})
2385 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302386 }
npujarec5762e2020-01-01 14:08:48 +05302387 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302388 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002389 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302390 log.Fields{
2391 "intf-id": intfID,
2392 "onu-id": onuID,
2393 "gemPort": gemPort,
2394 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002395 return
2396 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002397 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302398 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002399 "gem-port-id": gemPort,
2400 "intf-id": intfID,
2401 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002402 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002403}
2404
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002405//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302406func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002407 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002408
2409 if packetIn.IntfType == "pon" {
2410 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002411 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002412 onuID, uniID := packetIn.OnuId, packetIn.UniId
2413 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 +00002414
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002415 if packetIn.PortNo != 0 {
2416 logicalPortNum = packetIn.PortNo
2417 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002418 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002419 }
2420 // 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 +00002421 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002422 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002423 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002424 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002425
2426 if logger.V(log.DebugLevel) {
2427 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2428 log.Fields{
2429 "logical-port-num": logicalPortNum,
2430 "intf-type": packetIn.IntfType,
2431 "packet": hex.EncodeToString(packetIn.Pkt),
2432 })
2433 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002434 return logicalPortNum, nil
2435}
2436
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002437//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002438func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002439 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002440
2441 ctag, priority, err := getCTagFromPacket(ctx, packet)
2442 if err != nil {
2443 return 0, err
2444 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302445
Esin Karaman7fb80c22020-07-16 14:23:33 +00002446 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002447 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002448 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002449 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002450 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302451 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002452 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302453 log.Fields{
2454 "pktinkey": pktInkey,
2455 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002456
2457 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002458 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302459 //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 +00002460 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302461 if err == nil {
2462 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002463 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302464 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002465 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002466 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302467 log.Fields{
2468 "pktinkey": pktInkey,
2469 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302470 return gemPortID, nil
2471 }
2472 }
Shrey Baid26912972020-04-16 21:02:31 +05302473 return uint32(0), olterrors.NewErrNotFound("gem-port",
2474 log.Fields{
2475 "pktinkey": pktInkey,
2476 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002477
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002478}
2479
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002480func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2481 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002482 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002483 classifier[PacketTagType] = DoubleTag
2484 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002485 /* We manage flowId resource pool on per PON port basis.
2486 Since this situation is tricky, as a hack, we pass the NNI port
2487 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002488 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002489 on NNI port, use onu_id as -1 (invalid)
2490 ****************** CAVEAT *******************
2491 This logic works if the NNI Port Id falls within the same valid
2492 range of PON Port Ids. If this doesn't work for some OLT Vendor
2493 we need to have a re-look at this.
2494 *********************************************
2495 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002496 onuID := -1
2497 uniID := -1
2498 gemPortID := -1
2499 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002500 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302501 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302502 return olterrors.NewErrNotFound("nni-intreface-id",
2503 log.Fields{
2504 "classifier": classifier,
2505 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002506 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302507 }
2508
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002509 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002510 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002511 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002512 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002513
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002514 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2515 log.Fields{
2516 "classifier": classifier,
2517 "action": action,
2518 "flowId": logicalFlow.Id,
2519 "intf-id": networkInterfaceID})
2520
David K. Bainbridge794735f2020-02-11 21:01:37 -08002521 classifierProto, err := makeOpenOltClassifierField(classifier)
2522 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002523 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002524 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002525 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002526 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002527 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002528 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002529 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002530 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002531 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2532 OnuId: int32(onuID), // OnuId not required
2533 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002534 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002535 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002536 AllocId: int32(allocID), // AllocId not used
2537 NetworkIntfId: int32(networkInterfaceID),
2538 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002539 Classifier: classifierProto,
2540 Action: actionProto,
2541 Priority: int32(logicalFlow.Priority),
2542 Cookie: logicalFlow.Cookie,
2543 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002544 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002545 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002546 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002547 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002548 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002549}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002550
Esin Karamanae41e2b2019-12-17 18:13:13 +00002551//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2552func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2553 var packetType string
2554 ovid, ivid := false, false
2555 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2556 vid := vlanID & VlanvIDMask
2557 if vid != ReservedVlan {
2558 ovid = true
2559 }
2560 }
2561 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2562 vid := uint32(metadata)
2563 if vid != ReservedVlan {
2564 ivid = true
2565 }
2566 }
2567 if ovid && ivid {
2568 packetType = DoubleTag
2569 } else if !ovid && !ivid {
2570 packetType = Untagged
2571 } else {
2572 packetType = SingleTag
2573 }
2574 return packetType
2575}
2576
2577//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002578func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002579 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002580 action := make(map[string]interface{})
2581 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2582 action[TrapToHost] = true
2583 /* We manage flowId resource pool on per PON port basis.
2584 Since this situation is tricky, as a hack, we pass the NNI port
2585 index (network_intf_id) as PON port Index for the flowId resource
2586 pool. Also, there is no ONU Id available for trapping packets
2587 on NNI port, use onu_id as -1 (invalid)
2588 ****************** CAVEAT *******************
2589 This logic works if the NNI Port Id falls within the same valid
2590 range of PON Port Ids. If this doesn't work for some OLT Vendor
2591 we need to have a re-look at this.
2592 *********************************************
2593 */
2594 onuID := -1
2595 uniID := -1
2596 gemPortID := -1
2597 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002598 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002599 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302600 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002601 "classifier": classifier,
2602 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002603 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002604 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002605 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002606 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002607 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002608 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002609
David K. Bainbridge794735f2020-02-11 21:01:37 -08002610 classifierProto, err := makeOpenOltClassifierField(classifier)
2611 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002612 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002613 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002614 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002615 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002616 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002617 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002618 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002619 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002620 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2621 OnuId: int32(onuID), // OnuId not required
2622 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002623 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002624 FlowType: Downstream,
2625 AllocId: int32(allocID), // AllocId not used
2626 NetworkIntfId: int32(networkInterfaceID),
2627 GemportId: int32(gemPortID), // GemportId not used
2628 Classifier: classifierProto,
2629 Action: actionProto,
2630 Priority: int32(logicalFlow.Priority),
2631 Cookie: logicalFlow.Cookie,
2632 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002633 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002634 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002635 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002636 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002637
David K. Bainbridge794735f2020-02-11 21:01:37 -08002638 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002639}
2640
salmansiddiqui7ac62132019-08-22 03:58:50 +00002641func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2642 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302643 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002644 }
2645 if Dir == tp_pb.Direction_UPSTREAM {
2646 return "upstream", nil
2647 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2648 return "downstream", nil
2649 }
2650 return "", nil
2651}
2652
Kent Hagermane6ff1012020-07-14 15:07:53 -04002653// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302654func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002655 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002656 tpID uint32, uni string) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002657 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002658 intfID := args[IntfID]
2659 onuID := args[OnuID]
2660 uniID := args[UniID]
2661 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002662 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002663 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002664 gemToAes := make(map[uint32]bool)
2665
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002666 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002667 var direction = tp_pb.Direction_UPSTREAM
2668 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002669 case *tp_pb.TechProfileInstance:
Gamze Abaka7650be62021-02-26 10:50:36 +00002670 if IsUpstream(actionInfo[Output].(uint32)) {
2671 attributes = TpInst.UpstreamGemPortAttributeList
2672 } else {
2673 attributes = TpInst.DownstreamGemPortAttributeList
2674 direction = tp_pb.Direction_DOWNSTREAM
2675 }
2676 default:
2677 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
2678 return
2679 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002680
2681 if len(gemPorts) == 1 {
2682 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002683 gemPortID = gemPorts[0]
2684 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002685 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2686 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002687 pBitMap := attributes[idx].PbitMap
2688 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2689 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2690 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
2691 // this pcp bit traffic.
2692 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2693 if pbitSet == pbit1 {
2694 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2695 pbitToGem[pcp] = gemID
2696 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002697 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002698 }
2699 }
2700 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002701 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2702 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2703 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002704 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002705 }
2706
Gamze Abaka7650be62021-02-26 10:50:36 +00002707 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2708 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2709
salmansiddiqui7ac62132019-08-22 03:58:50 +00002710 if ipProto, ok := classifierInfo[IPProto]; ok {
2711 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002712 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002713 "tp-id": tpID,
2714 "alloc-id": allocID,
2715 "intf-id": intfID,
2716 "onu-id": onuID,
2717 "uni-id": uniID,
2718 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002719 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002720 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002721 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002722 }
2723
Girish Gowdra32625212020-04-29 11:26:35 -07002724 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002725 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302726 log.Fields{
2727 "intf-id": intfID,
2728 "onu-id": onuID,
2729 "uni-id": uniID,
2730 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002731 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002732 logger.Warn(ctx, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002733 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002734 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002735 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002736 return
2737 }
2738 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002739 if ethType.(uint32) == EapEthType {
2740 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002741 "intf-id": intfID,
2742 "onu-id": onuID,
2743 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002744 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002745 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002746 var vlanID uint32
2747 if val, ok := classifierInfo[VlanVid]; ok {
2748 vlanID = (val.(uint32)) & VlanvIDMask
2749 } else {
2750 vlanID = DefaultMgmtVlan
2751 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002752 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002753 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002754 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002755 } else if ethType.(uint32) == PPPoEDEthType {
2756 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2757 "tp-id": tpID,
2758 "alloc-id": allocID,
2759 "intf-id": intfID,
2760 "onu-id": onuID,
2761 "uni-id": uniID,
2762 })
2763 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002764 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002765 logger.Warn(ctx, err)
2766 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002767 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002768 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002769 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002770 "intf-id": intfID,
2771 "onu-id": onuID,
2772 "uni-id": uniID,
2773 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002774 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002775 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002776 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002777 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002778 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002779 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002780 "intf-id": intfID,
2781 "onu-id": onuID,
2782 "uni-id": uniID,
2783 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002784 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002785 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002786 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002787 }
2788 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002789 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05302790 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002791 "intf-id": intfID,
2792 "onu-id": onuID,
2793 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05302794 "classifier": classifierInfo,
2795 "action": actionInfo,
2796 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002797 return
2798 }
2799 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002800 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002801 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002802 logger.Warn(ctx, err)
2803 }
2804 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002805}
2806
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002807func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002808 f.gemToFlowIDsKey.RLock()
2809 flowIDList := f.gemToFlowIDs[gemPortID]
2810 f.gemToFlowIDsKey.RUnlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002811 return len(flowIDList) > 1
2812
Gamze Abakafee36392019-10-03 11:17:24 +00002813}
2814
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002815func (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 +05302816 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002817 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2818 for _, currentGemPort := range currentGemPorts {
2819 for _, tpGemPort := range tpGemPorts {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002820 if (currentGemPort == tpGemPort.GemportId) && (currentGemPort != gemPortID) {
Gamze Abakafee36392019-10-03 11:17:24 +00002821 return true, currentGemPort
2822 }
2823 }
2824 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00002825 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
2826 return false, 0
2827}
Girish Gowdra54934262019-11-13 14:19:55 +05302828
Gamze Abakacb0e6772021-06-10 08:32:12 +00002829func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002830 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
2831 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
2832 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 +00002833 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05302834 for i := 0; i < len(tpInstances); i++ {
2835 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00002836 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002837 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Gamze Abakacb0e6772021-06-10 08:32:12 +00002838 logger.Debugw(ctx, "alloc-is-in-use",
2839 log.Fields{
2840 "device-id": f.deviceHandler.device.Id,
2841 "intfID": sq.intfID,
2842 "onuID": sq.onuID,
2843 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002844 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00002845 })
2846 return true
Girish Gowdra54934262019-11-13 14:19:55 +05302847 }
2848 }
2849 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00002850 return false
Gamze Abakafee36392019-10-03 11:17:24 +00002851}
2852
Neha Sharma96b7bf22020-06-15 10:37:32 +00002853func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002854 for _, field := range flows.GetOfbFields(flow) {
2855 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002856 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002857 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002858 } else if field.Type == flows.ETH_DST {
2859 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002860 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07002861 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002862 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002863 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002864 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002865 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002866 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002867 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05302868 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00002869 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002870 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002871 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002872 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002873 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002874 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002875 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002876 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002877 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002878 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002879 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002880 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002881 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002882 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002883 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002884 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002885 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002886 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002887 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07002888 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002889 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002890 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002891 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002892 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002893 return
2894 }
2895 }
2896}
2897
Neha Sharma96b7bf22020-06-15 10:37:32 +00002898func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07002899 for _, action := range flows.GetActions(flow) {
2900 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002901 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002902 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002903 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002904 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002905 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002906 }
Scott Baker355d1742019-10-24 10:57:52 -07002907 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002908 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00002909 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002910 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002911 if out := action.GetPush(); out != nil {
2912 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002913 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002914 } else {
2915 actionInfo[PushVlan] = true
2916 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00002917 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05302918 log.Fields{
2919 "push-tpid": actionInfo[TPID].(uint32),
2920 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002921 }
2922 }
Scott Baker355d1742019-10-24 10:57:52 -07002923 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002924 if out := action.GetSetField(); out != nil {
2925 if field := out.GetField(); field != nil {
2926 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00002927 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002928 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002929 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
2930 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002931 }
2932 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002933 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002934 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002935 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002936 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002937 }
2938 }
2939 return nil
2940}
2941
Neha Sharma96b7bf22020-06-15 10:37:32 +00002942func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00002943 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00002944 fieldtype := ofbField.GetType()
2945 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00002946 if vlan := ofbField.GetVlanVid(); vlan != 0 {
2947 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00002948 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002949 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002950 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00002951 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00002952 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
2953 pcp := ofbField.GetVlanPcp()
2954 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002955 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002956 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002957 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00002958 }
2959 }
2960}
2961
Neha Sharma96b7bf22020-06-15 10:37:32 +00002962func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00002963 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002964 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00002965 } else {
2966 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00002967 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002968 }
2969}
2970
Neha Sharma96b7bf22020-06-15 10:37:32 +00002971func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002972 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002973 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002974 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2975 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002976 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002977 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00002978 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05302979 log.Fields{
2980 "newinport": classifierInfo[InPort].(uint32),
2981 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002982 } else {
Shrey Baid26912972020-04-16 21:02:31 +05302983 return olterrors.NewErrNotFound("child-in-port",
2984 log.Fields{
2985 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
2986 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002987 }
2988 }
2989 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002990 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002991 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07002992 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002993 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002994 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00002995 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05302996 log.Fields{
2997 "newoutport": actionInfo[Output].(uint32),
2998 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002999 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303000 return olterrors.NewErrNotFound("out-port",
3001 log.Fields{
3002 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3003 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003004 }
3005 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3006 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003007 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003008 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003009 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303010 log.Fields{
3011 "newinport": actionInfo[Output].(uint32),
3012 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003013 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303014 return olterrors.NewErrNotFound("nni-port",
3015 log.Fields{
3016 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3017 "in-port": classifierInfo[InPort].(uint32),
3018 "out-port": actionInfo[Output].(uint32),
3019 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003020 }
3021 }
3022 }
3023 return nil
3024}
Gamze Abakafee36392019-10-03 11:17:24 +00003025
Neha Sharma96b7bf22020-06-15 10:37:32 +00003026func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003027 /* Metadata 8 bytes:
3028 Most Significant 2 Bytes = Inner VLAN
3029 Next 2 Bytes = Tech Profile ID(TPID)
3030 Least Significant 4 Bytes = Port ID
3031 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3032 subscriber related flows.
3033 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003034 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003035 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003036 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003037 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003038 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003039 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003040}
3041
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003042func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3043 for _, sliceElement := range slice {
3044 if sliceElement == item {
3045 return slice
3046 }
3047 }
3048 return append(slice, item)
3049}
3050
3051func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003052 for _, sliceElement := range slice {
3053 if sliceElement == item {
3054 return slice
3055 }
3056 }
3057 return append(slice, item)
3058}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303059
3060// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003061func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303062
3063 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3064 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003065 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003066 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003067 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003068 log.Fields{
3069 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003070 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003071 return uint32(0), err
3072 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003073 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303074 return intfID, nil
3075 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003076 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003077 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003078 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003079 log.Fields{
3080 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003081 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003082 return uint32(0), err
3083 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003084 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303085 return intfID, nil
3086 }
3087 return uint32(0), nil
3088}
3089
3090// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003091func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3092 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3093 if err != nil {
3094 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3095 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3096 return
3097 }
3098 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003099
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003100 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003101 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003102 f.packetInGemPortLock.RUnlock()
3103
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303104 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003105 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003106 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 +05303107 log.Fields{
3108 "pktinkey": pktInkey,
3109 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003110 return
3111 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303112 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003113 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003114 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003115 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003116
npujarec5762e2020-01-01 14:08:48 +05303117 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003118 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 +05303119 log.Fields{
3120 "pktinkey": pktInkey,
3121 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303122}
3123
Esin Karaman7fb80c22020-07-16 14:23:33 +00003124//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3125func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3126 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003127 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003128 return 0, 0, errors.New("invalid packet length")
3129 }
3130 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3131 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3132
3133 var index int8
3134 if outerEthType == 0x8100 {
3135 if innerEthType == 0x8100 {
3136 // q-in-q 802.1ad or 802.1q double tagged packet.
3137 // get the inner vlanId
3138 index = 18
3139 } else {
3140 index = 14
3141 }
3142 priority := (packet[index] >> 5) & 0x7
3143 //13 bits composes vlanId value
3144 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3145 return vlan, priority, nil
3146 }
3147 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3148 return 0, 0, nil
3149}
3150
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003151func (f *OpenOltFlowMgr) loadFlowIDsForGemAndGemIDsForFlow(ctx context.Context) {
3152 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - start")
3153 f.onuGemInfoLock.RLock()
3154 f.gemToFlowIDsKey.Lock()
3155 f.flowIDToGemsLock.Lock()
3156 for _, og := range f.onuGemInfoMap {
3157 for _, gem := range og.GemPorts {
3158 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, f.ponPortIdx, gem)
3159 if err != nil {
3160 f.gemToFlowIDs[gem] = flowIDs
3161 for _, flowID := range flowIDs {
3162 if _, ok := f.flowIDToGems[flowID]; !ok {
3163 f.flowIDToGems[flowID] = []uint32{gem}
3164 } else {
3165 f.flowIDToGems[flowID] = appendUnique32bit(f.flowIDToGems[flowID], gem)
3166 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303167 }
3168 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303169 }
3170 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003171 f.flowIDToGemsLock.Unlock()
3172 f.gemToFlowIDsKey.Unlock()
3173 f.onuGemInfoLock.RUnlock()
3174 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - end")
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303175}
Esin Karamanccb714b2019-11-29 15:02:06 +00003176
Girish Gowdra9602eb42020-09-09 15:50:39 -07003177//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3178// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003179func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003180 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003181 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3182 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003183 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003184 "flow-id": flow.Id,
3185 "device-id": f.deviceHandler.device.Id})
3186 // Remove from device
3187 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3188 // DKB
3189 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3190 log.Fields{
3191 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003192 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003193 return err
3194 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003195
3196 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003197}
3198
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003199func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, ponID uint32, onuID uint32, uniID uint32) *ic.InterAdapterTechProfileDownloadMessage {
3200 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003201 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003202 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
3203 return nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003204 }
3205
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003206 switch tpInst := tpInst.(type) {
3207 case *tp_pb.TechProfileInstance:
3208 logger.Debugw(ctx, "fetched-tp-instance-successfully--formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
3209 return &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID,
3210 TpInstancePath: tpPath,
3211 TechTpInstance: &ic.InterAdapterTechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003212 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003213 case *openoltpb2.EponTechProfileInstance:
3214 return &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID,
3215 TpInstancePath: tpPath,
3216 TechTpInstance: &ic.InterAdapterTechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
3217 }
3218 default:
3219 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003220 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003221 return nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003222}
3223
Girish Gowdrabcf98af2021-07-01 08:24:42 -07003224func (f *OpenOltFlowMgr) getOnuGemInfoList(ctx context.Context) []rsrcMgr.OnuGemInfo {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003225 var onuGemInfoLst []rsrcMgr.OnuGemInfo
3226 f.onuGemInfoLock.RLock()
3227 defer f.onuGemInfoLock.RUnlock()
3228 for _, v := range f.onuGemInfoMap {
3229 onuGemInfoLst = append(onuGemInfoLst, *v)
3230 }
3231 return onuGemInfoLst
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003232}