blob: d6bf38e5dd1c9e7b7a43751e9016f035c591bb15 [file] [log] [blame]
manikkaraj kbf256be2019-03-25 00:13:48 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
manikkaraj kbf256be2019-03-25 00:13:48 +053019
20import (
21 "context"
Matteo Scandolo6056e822019-11-13 14:05:29 -080022 "encoding/hex"
Girish Gowdracefae192020-03-19 18:14:10 -070023 "errors"
manikkaraj kbf256be2019-03-25 00:13:48 +053024 "fmt"
Gamze Abaka7650be62021-02-26 10:50:36 +000025 "strconv"
serkant.uluderya4aff1862020-09-17 23:35:26 +030026 "strings"
27 "sync"
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070028 "time"
serkant.uluderya4aff1862020-09-17 23:35:26 +030029
Mahir Gunyel199570a2021-07-04 15:39:36 -070030 "github.com/opencord/voltha-lib-go/v6/pkg/meters"
31
Girish Gowdra4c3d4602021-07-22 16:33:37 -070032 "github.com/opencord/voltha-lib-go/v6/pkg/flows"
33 "github.com/opencord/voltha-lib-go/v6/pkg/log"
34 tp "github.com/opencord/voltha-lib-go/v6/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080035 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070036 "github.com/opencord/voltha-protos/v4/go/common"
37 ic "github.com/opencord/voltha-protos/v4/go/inter_container"
38 ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
39 openoltpb2 "github.com/opencord/voltha-protos/v4/go/openolt"
40 tp_pb "github.com/opencord/voltha-protos/v4/go/tech_profile"
41 "github.com/opencord/voltha-protos/v4/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040042
Thomas Lee S94109f12020-03-03 16:39:29 +053043 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000044 "google.golang.org/grpc/codes"
45 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053046)
47
48const (
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070049 //IPProtoDhcp flow category
50 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053051
Girish Gowdraa09aeab2020-09-14 16:30:52 -070052 //IgmpProto proto value
53 IgmpProto = 2
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070054
55 //EapEthType eapethtype value
56 EapEthType = 0x888e
57 //LldpEthType lldp ethtype value
58 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000059 //IPv4EthType IPv4 ethernet type value
60 IPv4EthType = 0x800
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -030061 //PPPoEDEthType PPPoE discovery ethernet type value
62 PPPoEDEthType = 0x8863
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070063
Andrea Campanella7acc0b92020-02-14 09:20:49 +010064 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
65 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040066
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070067 //DefaultMgmtVlan default vlan value
68 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053069
manikkaraj kbf256be2019-03-25 00:13:48 +053070 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070071
David K. Bainbridge82efc492019-09-04 09:57:11 -070072 //Upstream constant
73 Upstream = "upstream"
74 //Downstream constant
75 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000076 //Multicast constant
77 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070078 //PacketTagType constant
79 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070080 //Untagged constant
81 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070082 //SingleTag constant
83 SingleTag = "single_tag"
84 //DoubleTag constant
85 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053086
87 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070088
89 //EthType constant
90 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +000091 //EthDst constant
92 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070093 //TPID constant
94 TPID = "tpid"
95 //IPProto constant
96 IPProto = "ip_proto"
97 //InPort constant
98 InPort = "in_port"
99 //VlanVid constant
100 VlanVid = "vlan_vid"
101 //VlanPcp constant
102 VlanPcp = "vlan_pcp"
103
104 //UDPDst constant
105 UDPDst = "udp_dst"
106 //UDPSrc constant
107 UDPSrc = "udp_src"
108 //Ipv4Dst constant
109 Ipv4Dst = "ipv4_dst"
110 //Ipv4Src constant
111 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700112 //Metadata constant
113 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700114 //TunnelID constant
115 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700116 //Output constant
117 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000118 //GroupID constant
119 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700120 // Actions
121
122 //PopVlan constant
123 PopVlan = "pop_vlan"
124 //PushVlan constant
125 PushVlan = "push_vlan"
126 //TrapToHost constant
127 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400128 //MaxMeterBand constant
129 MaxMeterBand = 2
130 //VlanPCPMask contant
131 VlanPCPMask = 0xFF
132 //VlanvIDMask constant
133 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000134 //IntfID constant
135 IntfID = "intfId"
136 //OnuID constant
137 OnuID = "onuId"
138 //UniID constant
139 UniID = "uniId"
140 //PortNo constant
141 PortNo = "portNo"
142 //AllocID constant
143 AllocID = "allocId"
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000144 //GemID constant
145 GemID = "gemId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000146
147 //NoneOnuID constant
148 NoneOnuID = -1
149 //NoneUniID constant
150 NoneUniID = -1
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700151
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700152 // Max number of flows that can be queued per ONU
153 maxConcurrentFlowsPerOnu = 20
manikkaraj kbf256be2019-03-25 00:13:48 +0530154
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700155 bitMapPrefix = "0b"
156 pbit1 = '1'
157)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400158
Gamze Abakafee36392019-10-03 11:17:24 +0000159type schedQueue struct {
160 direction tp_pb.Direction
161 intfID uint32
162 onuID uint32
163 uniID uint32
164 tpID uint32
165 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700166 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000167 meterID uint32
168 flowMetadata *voltha.FlowMetadata
169}
170
Gamze Abaka7650be62021-02-26 10:50:36 +0000171type flowContext struct {
172 intfID uint32
173 onuID uint32
174 uniID uint32
175 portNo uint32
176 classifier map[string]interface{}
177 action map[string]interface{}
178 logicalFlow *ofp.OfpFlowStats
179 allocID uint32
180 gemPortID uint32
181 tpID uint32
182 pbitToGem map[uint32]uint32
183 gemToAes map[uint32]bool
184}
185
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700186// This control block is created per flow add/remove and pushed on the incomingFlows channel slice
187// The flowControlBlock is then picked by the perOnuFlowHandlerRoutine for further processing.
188// There is on perOnuFlowHandlerRoutine routine per ONU that constantly monitors for any incoming
189// flow and processes it serially
190type flowControlBlock struct {
191 ctx context.Context // Flow handler context
192 addFlow bool // if true flow to be added, else removed
193 flow *voltha.OfpFlowStats // Flow message
194 flowMetadata *voltha.FlowMetadata // FlowMetadata that contains flow meter information. This can be nil for Flow remove
195 errChan *chan error // channel to report the Flow handling error
Esin Karamanccb714b2019-11-29 15:02:06 +0000196}
197
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700198//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530199type OpenOltFlowMgr struct {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700200 ponPortIdx uint32 // Pon Port this FlowManager is responsible for
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700201 techprofile tp.TechProfileIf
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700202 deviceHandler *DeviceHandler
203 grpMgr *OpenOltGroupMgr
204 resourceMgr *rsrcMgr.OpenOltResourceMgr
205
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700206 gemToFlowIDs map[uint32][]uint64 // gem port id to flow ids
207 gemToFlowIDsKey sync.RWMutex // lock to be used to access the gemToFlowIDs map
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700208
209 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
210 packetInGemPortLock sync.RWMutex
211
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700212 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700213 onuGemInfoMap map[uint32]*rsrcMgr.OnuGemInfo //onu, gem and uni info local cache -> map of onuID to OnuGemInfo
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700214 // We need to have a global lock on the onuGemInfo map
Girish Gowdra9602eb42020-09-09 15:50:39 -0700215 onuGemInfoLock sync.RWMutex
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700216
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700217 flowIDToGems map[uint64][]uint32
218 flowIDToGemsLock sync.RWMutex
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700219
220 // Slice of channels. Each channel in slice, index by ONU ID, queues flows per ONU.
221 // A go routine per ONU, waits on the unique channel (indexed by ONU ID) for incoming flows (add/remove)
222 incomingFlows []chan flowControlBlock
manikkaraj kbf256be2019-03-25 00:13:48 +0530223}
224
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700225//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700226func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000227 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530228 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530229 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530230
manikkaraj kbf256be2019-03-25 00:13:48 +0530231 flowMgr.deviceHandler = dh
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700232 flowMgr.ponPortIdx = ponPortIdx
Girish Gowdra9602eb42020-09-09 15:50:39 -0700233 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530234 flowMgr.resourceMgr = rMgr
Neha Sharma96b7bf22020-06-15 10:37:32 +0000235 if err = flowMgr.populateTechProfilePerPonPort(ctx); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700236 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"err": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530237 return nil
238 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700239 flowMgr.gemToFlowIDs = make(map[uint32][]uint64)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530240 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700241 flowMgr.flowIDToGems = make(map[uint64][]uint32)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700242
243 // Create a slice of buffered channels for handling concurrent flows per ONU.
244 // The additional entry (+1) is to handle the NNI trap flows on a separate channel from individual ONUs channel
245 flowMgr.incomingFlows = make([]chan flowControlBlock, MaxOnusPerPon+1)
246 for i := range flowMgr.incomingFlows {
247 flowMgr.incomingFlows[i] = make(chan flowControlBlock, maxConcurrentFlowsPerOnu)
248 // Spin up a go routine to handling incoming flows (add/remove).
249 // There will be on go routine per ONU.
250 // This routine will be blocked on the flowMgr.incomingFlows[onu-id] channel for incoming flows.
251 go flowMgr.perOnuFlowHandlerRoutine(flowMgr.incomingFlows[i])
252 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700253 flowMgr.onuGemInfoMap = make(map[uint32]*rsrcMgr.OnuGemInfo)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530254 //Load the onugem info cache from kv store on flowmanager start
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700255 onuIDStart := flowMgr.deviceHandler.deviceInfo.OnuIdStart
256 onuIDEnd := flowMgr.deviceHandler.deviceInfo.OnuIdEnd
257 for onuID := onuIDStart; onuID <= onuIDEnd; onuID++ {
258 // check for a valid serial number in onuGem as GetOnuGemInfo can return nil error in case of nothing found in the path.
259 onugem, err := rMgr.GetOnuGemInfo(ctx, onuID, ponPortIdx)
260 if err == nil && onugem != nil && onugem.SerialNumber != "" {
261 flowMgr.onuGemInfoMap[onuID] = onugem
262 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530263 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700264
265 //Load flowID list per gem map And gemIDs per flow per interface from the kvstore.
266 flowMgr.loadFlowIDsForGemAndGemIDsForFlow(ctx)
267
Esin Karamanccb714b2019-11-29 15:02:06 +0000268 //load interface to multicast queue map from kv store
Girish Gowdra9602eb42020-09-09 15:50:39 -0700269 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000270 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530271 return &flowMgr
272}
273
Kent Hagermane6ff1012020-07-14 15:07:53 -0400274func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700275 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
276 // Flow is not replicated in this case, we need to register the flow for a single gem-port
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700277 return f.registerFlowIDForGemAndGemIDForFlow(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowFromCore)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700278 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
279 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
280 for _, gemPort := range deviceFlow.PbitToGemport {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700281 if err := f.registerFlowIDForGemAndGemIDForFlow(ctx, uint32(deviceFlow.AccessIntfId), gemPort, flowFromCore); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700282 return err
283 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700284 }
Gamze Abakafee36392019-10-03 11:17:24 +0000285 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700286 return nil
287}
288
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700289func (f *OpenOltFlowMgr) registerFlowIDForGemAndGemIDForFlow(ctx context.Context, accessIntfID uint32, gemPortID uint32, flowFromCore *ofp.OfpFlowStats) error {
290 // update gem->flows map
291 f.gemToFlowIDsKey.Lock()
292 flowIDList, ok := f.gemToFlowIDs[gemPortID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700293 if !ok {
294 flowIDList = []uint64{flowFromCore.Id}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700295 } else {
296 flowIDList = appendUnique64bit(flowIDList, flowFromCore.Id)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700297 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700298 f.gemToFlowIDs[gemPortID] = flowIDList
299 f.gemToFlowIDsKey.Unlock()
300
301 // update flow->gems map
302 f.flowIDToGemsLock.Lock()
303 if _, ok := f.flowIDToGems[flowFromCore.Id]; !ok {
304 f.flowIDToGems[flowFromCore.Id] = []uint32{gemPortID}
305 } else {
306 f.flowIDToGems[flowFromCore.Id] = appendUnique32bit(f.flowIDToGems[flowFromCore.Id], gemPortID)
307 }
308 f.flowIDToGemsLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700309
310 // update the flowids for a gem to the KVstore
311 return f.resourceMgr.UpdateFlowIDsForGem(ctx, accessIntfID, gemPortID, flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400312}
313
Girish Gowdra9602eb42020-09-09 15:50:39 -0700314func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000315 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
Andrea Campanellabfe08432020-09-11 17:07:03 +0200316 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000317 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530318 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700319 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530320
Neha Sharma96b7bf22020-06-15 10:37:32 +0000321 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530322 "device-id": f.deviceHandler.device.Id,
323 "intf-id": intfID,
324 "onu-id": onuID,
325 "uni-id": uniID,
326 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700327 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530328 "action": actionInfo,
329 "usmeter-iD": UsMeterID,
330 "dsmeter-iD": DsMeterID,
331 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400332 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
333 // is because the flow is an NNI flow and there would be no onu resources associated with it
334 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400335 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200336 cause := "no-onu-id-for-flow"
337 fields := log.Fields{
338 "onu": onuID,
339 "port-no": portNo,
340 "classifer": classifierInfo,
341 "action": actionInfo,
342 "device-id": f.deviceHandler.device.Id}
343 logger.Errorw(ctx, cause, fields)
344 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530345 }
346
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700347 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000348 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530349 "uni": uni,
350 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530351
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700352 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
353 "device-id": f.deviceHandler.device.Id,
354 "intf-id": intfID,
355 "onu-id": onuID,
356 "uni-id": uniID,
357 "port-no": portNo,
358 "classifier": classifierInfo,
359 "action": actionInfo,
360 "usmeter-id": UsMeterID,
361 "dsmeter-id": DsMeterID,
362 "tp-id": TpID})
363 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
364 if allocID == 0 || gemPorts == nil || TpInst == nil {
365 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
366 return olterrors.NewErrNotFound(
367 "alloc-id-gem-ports-tp-unavailable",
368 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400369 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700370 args := make(map[string]uint32)
371 args[IntfID] = intfID
372 args[OnuID] = onuID
373 args[UniID] = uniID
374 args[PortNo] = portNo
375 args[AllocID] = allocID
376
377 /* Flows can be added specific to gemport if p-bits are received.
378 * If no pbit mentioned then adding flows for all gemports
379 */
380 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
381
Andrea Campanellabfe08432020-09-11 17:07:03 +0200382 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530383}
384
salmansiddiqui7ac62132019-08-22 03:58:50 +0000385// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530386func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400387
Neha Sharma96b7bf22020-06-15 10:37:32 +0000388 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530389 log.Fields{"dir": sq.direction,
390 "intf-id": sq.intfID,
391 "onu-id": sq.onuID,
392 "uni-id": sq.uniID,
393 "tp-id": sq.tpID,
394 "meter-id": sq.meterID,
395 "tp-inst": sq.tpInst,
396 "flowmetadata": sq.flowMetadata,
397 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400398
Gamze Abakafee36392019-10-03 11:17:24 +0000399 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000400 if err != nil {
401 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400402 }
403
404 /* Lets make a simple assumption that if the meter-id is present on the KV store,
405 * then the scheduler and queues configuration is applied on the OLT device
406 * in the given direction.
407 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000408
Manikkaraj kb1d51442019-07-23 10:41:02 -0400409 var SchedCfg *tp_pb.SchedulerConfig
Girish Gowdraa482f272021-03-24 23:04:19 -0700410 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400411 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530412 return olterrors.NewErrNotFound("meter",
413 log.Fields{"intf-id": sq.intfID,
414 "onu-id": sq.onuID,
415 "uni-id": sq.uniID,
416 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400417 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000418
Girish Gowdraa482f272021-03-24 23:04:19 -0700419 if meterInfo != nil {
420 logger.Debugw(ctx, "scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id, "meter-id": sq.meterID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700421 if meterInfo.MeterID == sq.meterID {
Girish Gowdraa482f272021-03-24 23:04:19 -0700422 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, true); err != nil {
423 return err
424 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400425 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400426 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530427 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800428 "unsupported": "meter-id",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700429 "kv-store-meter-id": meterInfo.MeterID,
Shrey Baid26912972020-04-16 21:02:31 +0530430 "meter-id-in-flow": sq.meterID,
431 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400432 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000433
Neha Sharma96b7bf22020-06-15 10:37:32 +0000434 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530435 log.Fields{
436 "meter-id": sq.meterID,
437 "direction": Direction,
438 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000439
Gamze Abakafee36392019-10-03 11:17:24 +0000440 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700441 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Gamze Abakafee36392019-10-03 11:17:24 +0000442 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700443 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Girish Kumar8f73fe02019-12-09 13:19:37 +0000444 }
445
Girish Gowdraa482f272021-03-24 23:04:19 -0700446 found := false
447 meterInfo = &rsrcMgr.MeterInfo{}
Gamze Abakafee36392019-10-03 11:17:24 +0000448 if sq.flowMetadata != nil {
449 for _, meter := range sq.flowMetadata.Meters {
450 if sq.meterID == meter.MeterId {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700451 meterInfo.MeterID = meter.MeterId
Girish Gowdraa482f272021-03-24 23:04:19 -0700452 meterInfo.RefCnt = 1 // initialize it to 1, since this is the first flow that referenced the meter id.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000453 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700454 log.Fields{"meter": meter,
Shrey Baid26912972020-04-16 21:02:31 +0530455 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -0700456 found = true
Manikkaraj kb1d51442019-07-23 10:41:02 -0400457 break
458 }
459 }
460 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000461 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400462 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700463 if !found {
Thomas Lee S94109f12020-03-03 16:39:29 +0530464 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800465 "reason": "Could-not-get-meterbands-from-flowMetadata",
466 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530467 "meter-id": sq.meterID,
468 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400469 }
Gamze Abaka01174422021-03-10 06:55:27 +0000470
471 var TrafficShaping *tp_pb.TrafficShapingInfo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700472 if TrafficShaping, err = meters.GetTrafficShapingInfo(ctx, sq.flowMetadata.Meters[0]); err != nil {
Gamze Abaka01174422021-03-10 06:55:27 +0000473 return olterrors.NewErrInvalidValue(log.Fields{
474 "reason": "invalid-meter-config",
475 "meter-id": sq.meterID,
476 "device-id": f.deviceHandler.device.Id}, nil)
477 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400478
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700479 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000480 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400481
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700482 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530483 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
484 log.Fields{"intf-id": sq.intfID,
485 "direction": sq.direction,
486 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400487 }
488
salmansiddiqui7ac62132019-08-22 03:58:50 +0000489 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400490 * store the meter id on the KV store, for further reference.
491 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700492 if err := f.resourceMgr.StoreMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530493 return olterrors.NewErrAdapter("failed-updating-meter-id",
494 log.Fields{"onu-id": sq.onuID,
495 "meter-id": sq.meterID,
496 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400497 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000498 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530499 log.Fields{"direction": Direction,
Girish Gowdraa482f272021-03-24 23:04:19 -0700500 "meter-info": meterInfo,
501 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400502 return nil
503}
504
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700505func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700506 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000507
508 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530509 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
510 log.Fields{"intf-id": sq.intfID,
511 "direction": sq.direction,
512 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000513 }
514
Gamze Abakacb0e6772021-06-10 08:32:12 +0000515 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
516 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
517 log.Fields{
518 "direction": sq.direction,
519 "TrafficScheds": TrafficSched,
520 "device-id": f.deviceHandler.device.Id,
521 "intfID": sq.intfID,
522 "onuID": sq.onuID,
523 "uniID": sq.uniID})
524 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
525 IntfId: sq.intfID, OnuId: sq.onuID,
526 UniId: sq.uniID, PortNo: sq.uniPort,
527 TrafficScheds: TrafficSched}); err != nil {
528 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
529 }
530 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
531 "direction": sq.direction,
532 "traffic-queues": trafficQueues,
533 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000534 }
535
536 // On receiving the CreateTrafficQueues request, the driver should create corresponding
537 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000538 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530539 log.Fields{"direction": sq.direction,
540 "traffic-queues": trafficQueues,
541 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530542 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000543 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
544 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000545 TrafficQueues: trafficQueues,
546 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530547 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000548 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000549 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530550 "direction": sq.direction,
551 "traffic-queues": trafficQueues,
552 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000553
Esin Karamanccb714b2019-11-29 15:02:06 +0000554 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700555 multicastTrafficQueues := f.techprofile.GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance))
Esin Karamanccb714b2019-11-29 15:02:06 +0000556 if len(multicastTrafficQueues) > 0 {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700557 if _, present := f.grpMgr.GetInterfaceToMcastQueueMap(sq.intfID); !present { //assumed that there is only one queue per PON for the multicast service
Esin Karamanccb714b2019-11-29 15:02:06 +0000558 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
559 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000560 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000561 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700562 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000563 gemPortID: multicastQueuePerPonPort.GemportId,
564 servicePriority: multicastQueuePerPonPort.Priority,
565 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700566 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000567 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400568 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700569 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400570 return err
571 }
Shrey Baid26912972020-04-16 21:02:31 +0530572
Neha Sharma96b7bf22020-06-15 10:37:32 +0000573 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000574 }
575 }
576 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000577 return nil
578}
579
salmansiddiqui7ac62132019-08-22 03:58:50 +0000580// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530581func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400582
583 var Direction string
584 var SchedCfg *tp_pb.SchedulerConfig
585 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000586 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530587 log.Fields{
588 "direction": sq.direction,
589 "intf-id": sq.intfID,
590 "onu-id": sq.onuID,
591 "uni-id": sq.uniID,
592 "uni-port": sq.uniPort,
593 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000594 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700595 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400596 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000597 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700598 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400599 Direction = "downstream"
600 }
601
Girish Gowdraa482f272021-03-24 23:04:19 -0700602 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
Manikkaraj kb1d51442019-07-23 10:41:02 -0400603
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700604 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000605 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000606
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700607 TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000608 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530609 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
610 log.Fields{
611 "intf-id": sq.intfID,
612 "direction": sq.direction,
613 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000614 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400615
npujarec5762e2020-01-01 14:08:48 +0530616 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000617 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
618 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000619 TrafficQueues: TrafficQueues,
620 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000621 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530622 log.Fields{
623 "intf-id": sq.intfID,
624 "traffic-queues": TrafficQueues,
625 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400626 }
Gamze Abakacb0e6772021-06-10 08:32:12 +0000627 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id, "trafficQueues": TrafficQueues})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400628
Gamze Abakacb0e6772021-06-10 08:32:12 +0000629 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
630 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
631 IntfId: sq.intfID, OnuId: sq.onuID,
632 UniId: sq.uniID, PortNo: sq.uniPort,
633 TrafficScheds: TrafficSched}); err != nil {
634 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
635 log.Fields{
636 "intf-id": sq.intfID,
637 "traffic-schedulers": TrafficSched,
638 "onu-id": sq.onuID,
639 "uni-id": sq.uniID,
640 "uni-port": sq.uniPort}, err)
641 }
642
643 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
644 log.Fields{"device-id": f.deviceHandler.device.Id,
645 "intf-id": sq.intfID,
646 "onu-id": sq.onuID,
647 "uni-id": sq.uniID,
648 "uni-port": sq.uniPort})
649
650 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700651 allocID := sq.tpInst.(*tp_pb.TechProfileInstance).UsScheduler.AllocId
Gamze Abakacb0e6772021-06-10 08:32:12 +0000652 f.resourceMgr.FreeAllocID(ctx, sq.intfID, sq.onuID, sq.uniID, allocID)
653 // Delete the TCONT on the ONU.
654 uni := getUniPortPath(f.deviceHandler.device.Id, sq.intfID, int32(sq.onuID), int32(sq.uniID))
655 tpPath := f.getTPpath(ctx, sq.intfID, uni, sq.tpID)
656 if err := f.sendDeleteTcontToChild(ctx, sq.intfID, sq.onuID, sq.uniID, allocID, tpPath); err != nil {
657 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
658 log.Fields{
659 "intf": sq.intfID,
660 "onu-id": sq.onuID,
661 "uni-id": sq.uniID,
662 "device-id": f.deviceHandler.device.Id,
663 "alloc-id": allocID})
664 }
665 }
666 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000667
668 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400669 * delete the meter id on the KV store.
670 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700671 err = f.resourceMgr.RemoveMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400672 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530673 return olterrors.NewErrAdapter("unable-to-remove-meter",
674 log.Fields{
675 "onu": sq.onuID,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700676 "device-id": f.deviceHandler.device.Id,
677 "intf-id": sq.intfID,
678 "onu-id": sq.onuID,
679 "uni-id": sq.uniID,
680 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400681 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000682 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530683 log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530684 "dir": Direction,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700685 "device-id": f.deviceHandler.device.Id,
686 "intf-id": sq.intfID,
687 "onu-id": sq.onuID,
688 "uni-id": sq.uniID,
689 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400690 return err
691}
692
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 Gowdra4c3d4602021-07-22 16:33:37 -0700855 var err error
856 f.techprofile, err = tp.NewTechProfile(ctx, f.resourceMgr.PonRsrMgr, f.resourceMgr.PonRsrMgr.Backend,
857 f.resourceMgr.PonRsrMgr.Address, f.deviceHandler.cm.Backend.PathPrefix)
858 if err != nil || f.techprofile == nil {
859 logger.Errorw(ctx, "failed-to-allocate-to-techprofile-for-pon-port", log.Fields{"intfID": intfID, "err": err})
860 return fmt.Errorf("failed-to-allocate-tech-profile-for-pon-port--pon-%v-err-%v", intfID, err)
861 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400862 tpCount++
Neha Sharma96b7bf22020-06-15 10:37:32 +0000863 logger.Debugw(ctx, "init-tech-profile-done",
Shrey Baid26912972020-04-16 21:02:31 +0530864 log.Fields{
865 "intf-id": intfID,
866 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530867 }
868 }
869 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400870 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530871 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530872 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800873 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530874 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
875 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530876 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000877 logger.Infow(ctx, "populated-techprofile-for-ponports-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530878 log.Fields{
879 "numofTech": tpCount,
880 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
881 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530882 return nil
883}
884
Gamze Abaka7650be62021-02-26 10:50:36 +0000885func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
886 flowContext.classifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000887 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530888 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000889 "uplinkClassifier": flowContext.classifier,
890 "uplinkAction": flowContext.action})
891 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
Manikkaraj k884c1242019-04-11 16:26:42 +0530892 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530893}
894
Gamze Abaka7650be62021-02-26 10:50:36 +0000895func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
896 downlinkClassifier := flowContext.classifier
897 downlinkAction := flowContext.action
898
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700899 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000900 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530901 log.Fields{
902 "downlinkClassifier": downlinkClassifier,
903 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400904 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
905 if vlan, exists := downlinkClassifier[VlanVid]; exists {
906 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700907 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Gamze Abaka7650be62021-02-26 10:50:36 +0000908 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, flowContext.intfID, flowContext.onuID, flowContext.uniID) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000909 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530910 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000911 "flow": flowContext.logicalFlow,
Shrey Baid26912972020-04-16 21:02:31 +0530912 "device-id": f.deviceHandler.device.Id,
Gamze Abaka7650be62021-02-26 10:50:36 +0000913 "onu-id": flowContext.onuID,
914 "intf-id": flowContext.intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800915 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400916 }
917 }
918 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530919 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400920
Manikkaraj k884c1242019-04-11 16:26:42 +0530921 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700922 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400923 // vlan_vid is a uint32. must be type asserted as such or conversion fails
924 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530925 if ok {
926 downlinkAction[VlanVid] = dlClVid & 0xfff
927 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530928 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530929 "reason": "failed-to-convert-vlanid-classifier",
930 "vlan-id": VlanVid,
931 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530932 }
933
Gamze Abaka7650be62021-02-26 10:50:36 +0000934 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +0530935}
936
Gamze Abaka7650be62021-02-26 10:50:36 +0000937func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700938
Gamze Abaka7650be62021-02-26 10:50:36 +0000939 intfID := flowContext.intfID
940 onuID := flowContext.onuID
941 uniID := flowContext.uniID
942 classifier := flowContext.classifier
943 action := flowContext.action
944 allocID := flowContext.allocID
945 gemPortID := flowContext.gemPortID
946 tpID := flowContext.tpID
947 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +0000948 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530949 log.Fields{
950 "intf-id": intfID,
951 "onu-id": onuID,
952 "uni-id": uniID,
953 "device-id": f.deviceHandler.device.Id,
954 "classifier": classifier,
955 "action": action,
956 "direction": direction,
957 "alloc-id": allocID,
958 "gemport-id": gemPortID,
959 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700960
961 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000962 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +0530963 log.Fields{
964 "device-id": f.deviceHandler.device.Id,
965 "intf-id": intfID,
966 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800967 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530968 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800969 classifierProto, err := makeOpenOltClassifierField(classifier)
970 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530971 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530972 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000973 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +0530974 log.Fields{
975 "classifier": *classifierProto,
976 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +0000977 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800978 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530979 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530980 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000981 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +0530982 log.Fields{
983 "action": *actionProto,
984 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +0000985 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530986 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530987 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800988 log.Fields{
989 "classifier": classifier,
990 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +0530991 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800992 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530993 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700994
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700995 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700996 OnuId: int32(onuID),
997 UniId: int32(uniID),
998 FlowId: logicalFlow.Id,
999 FlowType: direction,
1000 AllocId: int32(allocID),
1001 NetworkIntfId: int32(networkIntfID),
1002 GemportId: int32(gemPortID),
1003 Classifier: classifierProto,
1004 Action: actionProto,
1005 Priority: int32(logicalFlow.Priority),
1006 Cookie: logicalFlow.Cookie,
1007 PortNo: flowContext.portNo,
1008 TechProfileId: tpID,
1009 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1010 PbitToGemport: flowContext.pbitToGem,
1011 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001012 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001013 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001014 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301015 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001016 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301017 log.Fields{"direction": direction,
1018 "device-id": f.deviceHandler.device.Id,
1019 "flow": flow,
1020 "intf-id": intfID,
1021 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001022
David K. Bainbridge794735f2020-02-11 21:01:37 -08001023 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301024}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001025
Gamze Abaka7650be62021-02-26 10:50:36 +00001026func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1027
1028 intfID := flowContext.intfID
1029 onuID := flowContext.onuID
1030 uniID := flowContext.uniID
1031 logicalFlow := flowContext.logicalFlow
1032 classifier := flowContext.classifier
1033 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301034
Neha Sharma96b7bf22020-06-15 10:37:32 +00001035 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301036 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301037 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001038 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301039 "action": action,
1040 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001041 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301042 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301043
1044 // Clear the action map
1045 for k := range action {
1046 delete(action, k)
1047 }
1048
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001049 action[TrapToHost] = true
1050 classifier[UDPSrc] = uint32(68)
1051 classifier[UDPDst] = uint32(67)
1052 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301053
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001054 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001055 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301056 log.Fields{
1057 "device-id": f.deviceHandler.device.Id,
1058 "intf-id": intfID,
1059 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001060 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301061 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301062
Neha Sharma96b7bf22020-06-15 10:37:32 +00001063 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301064 log.Fields{
1065 "ul_classifier": classifier,
1066 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001067 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301068 "intf-id": intfID,
1069 "onu-id": onuID,
1070 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301071
David K. Bainbridge794735f2020-02-11 21:01:37 -08001072 classifierProto, err := makeOpenOltClassifierField(classifier)
1073 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301074 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301075 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001076 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001077 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001078 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301079 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301080 }
1081
David K. Bainbridge794735f2020-02-11 21:01:37 -08001082 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001083 OnuId: int32(onuID),
1084 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001085 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001086 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001087 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001088 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001089 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301090 Classifier: classifierProto,
1091 Action: actionProto,
1092 Priority: int32(logicalFlow.Priority),
1093 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001094 PortNo: flowContext.portNo,
1095 TechProfileId: flowContext.tpID,
1096 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1097 PbitToGemport: flowContext.pbitToGem,
1098 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001099 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001100 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001101 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001102 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001103 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301104 log.Fields{
1105 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001106 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301107 "intf-id": intfID,
1108 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301109
David K. Bainbridge794735f2020-02-11 21:01:37 -08001110 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301111}
1112
Esin Karamanae41e2b2019-12-17 18:13:13 +00001113//addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001114func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1115 delete(flowContext.classifier, VlanVid)
1116 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001117}
1118
1119//addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001120func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1121
1122 intfID := flowContext.intfID
1123 onuID := flowContext.onuID
1124 uniID := flowContext.uniID
1125 logicalFlow := flowContext.logicalFlow
1126 classifier := flowContext.classifier
1127 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001128
Neha Sharma96b7bf22020-06-15 10:37:32 +00001129 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001130 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301131 return olterrors.NewErrNotFound("nni-interface-id",
1132 log.Fields{
1133 "classifier": classifier,
1134 "action": action,
1135 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001136 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001137 }
1138
1139 // Clear the action map
1140 for k := range action {
1141 delete(action, k)
1142 }
1143
1144 action[TrapToHost] = true
1145 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001146
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001147 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001148 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001149 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001150 }
1151
Neha Sharma96b7bf22020-06-15 10:37:32 +00001152 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301153 log.Fields{
1154 "ul_classifier": classifier,
1155 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001156 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301157 "device-id": f.deviceHandler.device.Id,
1158 "intf-id": intfID,
1159 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001160
David K. Bainbridge794735f2020-02-11 21:01:37 -08001161 classifierProto, err := makeOpenOltClassifierField(classifier)
1162 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301163 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001164 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001165 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301166 log.Fields{
1167 "classifier": *classifierProto,
1168 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001169 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001170 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301171 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001172 }
1173
David K. Bainbridge794735f2020-02-11 21:01:37 -08001174 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001175 OnuId: int32(onuID),
1176 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001177 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001178 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001179 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001180 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001181 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001182 Classifier: classifierProto,
1183 Action: actionProto,
1184 Priority: int32(logicalFlow.Priority),
1185 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001186 PortNo: flowContext.portNo,
1187 TechProfileId: flowContext.tpID,
1188 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1189 PbitToGemport: flowContext.pbitToGem,
1190 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001191 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001192
David K. Bainbridge794735f2020-02-11 21:01:37 -08001193 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001194 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 -08001195 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001196
David K. Bainbridge794735f2020-02-11 21:01:37 -08001197 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001198}
1199
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001200// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001201func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1202 intfID := flowContext.intfID
1203 onuID := flowContext.onuID
1204 uniID := flowContext.uniID
1205 portNo := flowContext.portNo
1206 allocID := flowContext.allocID
1207 gemPortID := flowContext.gemPortID
1208 logicalFlow := flowContext.logicalFlow
1209 classifier := flowContext.classifier
1210 action := flowContext.action
1211
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001212 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301213 log.Fields{
1214 "intf-id": intfID,
1215 "onu-id": onuID,
1216 "port-no": portNo,
1217 "alloc-id": allocID,
1218 "gemport-id": gemPortID,
1219 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001220 "flow": logicalFlow,
1221 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301222
1223 uplinkClassifier := make(map[string]interface{})
1224 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301225
manikkaraj kbf256be2019-03-25 00:13:48 +05301226 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001227 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001228 uplinkClassifier[PacketTagType] = SingleTag
1229 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001230 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301231 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001232 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001233 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001234 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301235 "device-id": f.deviceHandler.device.Id,
1236 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001237 "intf-id": intfID,
1238 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001239 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301240 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001241 //Add Uplink EthType Flow
1242 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301243 log.Fields{
1244 "ul_classifier": uplinkClassifier,
1245 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001246 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301247 "device-id": f.deviceHandler.device.Id,
1248 "intf-id": intfID,
1249 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301250
David K. Bainbridge794735f2020-02-11 21:01:37 -08001251 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1252 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301253 return olterrors.NewErrInvalidValue(log.Fields{
1254 "classifier": uplinkClassifier,
1255 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301256 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001257 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301258 log.Fields{
1259 "classifier": *classifierProto,
1260 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001261 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001262 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301263 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301264 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001265 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301266 log.Fields{
1267 "action": *actionProto,
1268 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001269 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301270 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301271 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001272 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301273 "action": action,
1274 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001275 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301276 }
1277
David K. Bainbridge794735f2020-02-11 21:01:37 -08001278 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001279 OnuId: int32(onuID),
1280 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001281 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001282 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001283 AllocId: int32(allocID),
1284 NetworkIntfId: int32(networkIntfID),
1285 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301286 Classifier: classifierProto,
1287 Action: actionProto,
1288 Priority: int32(logicalFlow.Priority),
1289 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001290 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001291 TechProfileId: flowContext.tpID,
1292 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1293 PbitToGemport: flowContext.pbitToGem,
1294 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001295 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001296 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001297 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001298 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001299 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301300 log.Fields{
1301 "device-id": f.deviceHandler.device.Id,
1302 "onu-id": onuID,
1303 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001304 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301305 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001306
David K. Bainbridge794735f2020-02-11 21:01:37 -08001307 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301308}
1309
David K. Bainbridge794735f2020-02-11 21:01:37 -08001310func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001311 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001312
1313 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1314 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1315 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001316 if vlanID != ReservedVlan {
1317 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001318 classifier.OVid = vid
1319 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301320 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001321 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1322 vid := uint32(metadata)
1323 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001324 classifier.IVid = vid
1325 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301326 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301327 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001328 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301329 classifier.OPbits = vlanPcp
1330 } else {
1331 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301332 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001333 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1334 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1335 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1336 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001337 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001338 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1339 classifier.PktTagType = pktTagType
1340
1341 switch pktTagType {
1342 case SingleTag:
1343 case DoubleTag:
1344 case Untagged:
1345 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001346 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301347 }
1348 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001349 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301350}
1351
Gamze Abaka724d0852020-03-18 12:10:24 +00001352func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001353 var actionCmd openoltpb2.ActionCmd
1354 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301355 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001356 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301357 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001358 if _, ok := actionInfo[VlanPcp]; ok {
1359 action.Cmd.RemarkInnerPbits = true
1360 action.IPbits = actionInfo[VlanPcp].(uint32)
1361 if _, ok := actionInfo[VlanVid]; ok {
1362 action.Cmd.TranslateInnerTag = true
1363 action.IVid = actionInfo[VlanVid].(uint32)
1364 }
1365 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001366 } else if _, ok := actionInfo[PushVlan]; ok {
1367 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301368 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001369 if _, ok := actionInfo[VlanPcp]; ok {
1370 action.OPbits = actionInfo[VlanPcp].(uint32)
1371 action.Cmd.RemarkOuterPbits = true
1372 if _, ok := classifierInfo[VlanVid]; ok {
1373 action.IVid = classifierInfo[VlanVid].(uint32)
1374 action.Cmd.TranslateInnerTag = true
1375 }
1376 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001377 } else if _, ok := actionInfo[TrapToHost]; ok {
1378 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301379 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001380 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301381 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001382 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301383}
1384
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001385// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001386func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001387 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301388}
1389
Gamze Abakafee36392019-10-03 11:17:24 +00001390// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001391func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301392 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001393 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1394
Gamze Abakafee36392019-10-03 11:17:24 +00001395 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301396 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001397 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301398 // return err
1399 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001400 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001401 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 +00001402 }
1403 return nil
1404}
1405
1406// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301407func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001408 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001409 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001410 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001411 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301412 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1413 log.Fields{
1414 "tp-id": tpID,
1415 "uni-port-name": uniPortName,
1416 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001417 }
1418 return nil
1419}
1420
David K. Bainbridge794735f2020-02-11 21:01:37 -08001421func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001422
1423 var intfID uint32
1424 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1425 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1426 */
1427 if deviceFlow.AccessIntfId != -1 {
1428 intfID = uint32(deviceFlow.AccessIntfId)
1429 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001430 // We need to log the valid interface ID.
1431 // 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 +00001432 intfID = uint32(deviceFlow.NetworkIntfId)
1433 }
1434
Neha Sharma96b7bf22020-06-15 10:37:32 +00001435 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301436 "flow": *deviceFlow,
1437 "device-id": f.deviceHandler.device.Id,
1438 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001439 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001440
1441 st, _ := status.FromError(err)
1442 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001443 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001444 "err": err,
1445 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301446 "device-id": f.deviceHandler.device.Id,
1447 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001448 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301449 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001450
1451 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001452 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301453 log.Fields{"err": err,
1454 "device-flow": deviceFlow,
1455 "device-id": f.deviceHandler.device.Id,
1456 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001457 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001458 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001459 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301460 log.Fields{
1461 "flow": *deviceFlow,
1462 "device-id": f.deviceHandler.device.Id,
1463 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001464
1465 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1466 if deviceFlow.AccessIntfId != -1 {
1467 // No need to register the flow if it is a trap on nni flow.
1468 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1469 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1470 return err
1471 }
1472 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001473 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001474}
1475
Neha Sharma96b7bf22020-06-15 10:37:32 +00001476func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1477 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301478 log.Fields{
1479 "flow": *deviceFlow,
1480 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001481 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001482 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001483 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001484 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301485 log.Fields{
1486 "err": err,
1487 "deviceFlow": deviceFlow,
1488 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001489 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001490 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001491 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001492 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001493
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001494 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001495 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001496 "of-flow-id": ofFlowID,
1497 "flow": *deviceFlow,
1498 "device-id": f.deviceHandler.device.Id,
1499 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001500 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301501}
1502
David K. Bainbridge794735f2020-02-11 21:01:37 -08001503func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001504
1505 classifierInfo := make(map[string]interface{})
1506 actionInfo := make(map[string]interface{})
1507
1508 classifierInfo[EthType] = uint32(LldpEthType)
1509 classifierInfo[PacketTagType] = Untagged
1510 actionInfo[TrapToHost] = true
1511
1512 // LLDP flow is installed to trap LLDP packets on the NNI port.
1513 // We manage flow_id resource pool on per PON port basis.
1514 // Since this situation is tricky, as a hack, we pass the NNI port
1515 // index (network_intf_id) as PON port Index for the flow_id resource
1516 // pool. Also, there is no ONU Id available for trapping LLDP packets
1517 // on NNI port, use onu_id as -1 (invalid)
1518 // ****************** CAVEAT *******************
1519 // This logic works if the NNI Port Id falls within the same valid
1520 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1521 // we need to have a re-look at this.
1522 // *********************************************
1523
1524 var onuID = -1
1525 var uniID = -1
1526 var gemPortID = -1
1527
Neha Sharma96b7bf22020-06-15 10:37:32 +00001528 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001529 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301530 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001531 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001532 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001533 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001534 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001535 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001536
David K. Bainbridge794735f2020-02-11 21:01:37 -08001537 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1538 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301539 return olterrors.NewErrInvalidValue(
1540 log.Fields{
1541 "classifier": classifierInfo,
1542 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001543 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001544 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301545 log.Fields{
1546 "classifier": *classifierProto,
1547 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001548 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001549 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301550 return olterrors.NewErrInvalidValue(
1551 log.Fields{
1552 "action": actionInfo,
1553 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001554 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001555 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301556 log.Fields{
1557 "action": *actionProto,
1558 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001559
1560 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1561 OnuId: int32(onuID), // OnuId not required
1562 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001563 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001564 FlowType: Downstream,
1565 NetworkIntfId: int32(networkInterfaceID),
1566 GemportId: int32(gemPortID),
1567 Classifier: classifierProto,
1568 Action: actionProto,
1569 Priority: int32(flow.Priority),
1570 Cookie: flow.Cookie,
1571 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001572 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001573 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301574 log.Fields{
1575 "flow": downstreamflow,
1576 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001577 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001578 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301579 log.Fields{
1580 "device-id": f.deviceHandler.device.Id,
1581 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001582 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001583
David K. Bainbridge794735f2020-02-11 21:01:37 -08001584 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301585}
1586
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001587func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1588 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001589}
1590
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001591//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001592func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001593 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1594 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1595 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001596 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301597 log.Fields{
1598 "intf-id": intfID,
1599 "onu-id": onuID,
1600 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001601 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001602 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301603 return nil, olterrors.NewErrNotFound("onu-child-device",
1604 log.Fields{
1605 "onu-id": onuID,
1606 "intf-id": intfID,
1607 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001608 }
1609 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1610 //better to ad the device to cache here.
1611 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1612 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001613 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301614 log.Fields{
1615 "intf-id": intfID,
1616 "onu-id": onuID,
1617 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001618 }
1619
1620 return onuDev.(*OnuDevice), nil
1621}
1622
1623//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001624func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1625 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301626 log.Fields{
1627 "pon-port": intfID,
1628 "onu-id": onuID,
1629 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001630 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001631 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001632 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301633 return nil, olterrors.NewErrNotFound("onu",
1634 log.Fields{
1635 "interface-id": parentPortNo,
1636 "onu-id": onuID,
1637 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001638 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301639 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001640 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301641 log.Fields{
1642 "device-id": f.deviceHandler.device.Id,
1643 "child_device_id": onuDevice.Id,
1644 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301645 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301646}
1647
Neha Sharma96b7bf22020-06-15 10:37:32 +00001648func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1649 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301650 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001651 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301652 log.Fields{
1653 "intf-id": intfID,
1654 "onu-id": onuID,
1655 "uni-id": uniID,
1656 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001657 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301658 }
1659
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001660 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpInstancePath: tpPath, GemPortId: gemPortID}
1661 logger.Infow(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301662 log.Fields{
1663 "msg": *delGemPortMsg,
1664 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001665 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301666 delGemPortMsg,
1667 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001668 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001669 onuDev.deviceType,
1670 onuDev.deviceID,
1671 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301672 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1673 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001674 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301675 "to-adapter": onuDev.deviceType,
1676 "onu-id": onuDev.deviceID,
1677 "proxyDeviceID": onuDev.proxyDeviceID,
1678 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301679 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001680 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301681 log.Fields{
1682 "msg": delGemPortMsg,
1683 "from-adapter": f.deviceHandler.device.Type,
1684 "to-adapter": onuDev.deviceType,
1685 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301686 return nil
1687}
1688
Neha Sharma96b7bf22020-06-15 10:37:32 +00001689func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1690 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301691 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001692 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301693 log.Fields{
1694 "intf-id": intfID,
1695 "onu-id": onuID,
1696 "uni-id": uniID,
1697 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001698 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301699 }
1700
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001701 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpInstancePath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001702 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301703 log.Fields{
1704 "msg": *delTcontMsg,
1705 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001706 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301707 delTcontMsg,
1708 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001709 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001710 onuDev.deviceType,
1711 onuDev.deviceID,
1712 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301713 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1714 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001715 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301716 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1717 "proxyDeviceID": onuDev.proxyDeviceID,
1718 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301719 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001720 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301721 log.Fields{
1722 "msg": delTcontMsg,
1723 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301724 return nil
1725}
1726
Girish Gowdrac3037402020-01-22 20:29:53 +05301727// Once the gemport is released for a given onu, it also has to be cleared from local cache
1728// which was used for deriving the gemport->logicalPortNo during packet-in.
1729// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1730// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001731func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001732 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301733 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001734 "gem-port-id": gemPortID,
1735 "intf-id": intfID,
1736 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001737 "device-id": f.deviceHandler.device.Id})
1738 f.onuGemInfoLock.RLock()
1739 onugem, ok := f.onuGemInfoMap[onuID]
1740 f.onuGemInfoLock.RUnlock()
1741 if !ok {
1742 logger.Warnw(ctx, "onu gem info already cleared from cache", log.Fields{
1743 "gem-port-id": gemPortID,
1744 "intf-id": intfID,
1745 "onu-id": onuID,
1746 "device-id": f.deviceHandler.device.Id})
1747 return
1748 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001749deleteLoop:
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001750 for j, gem := range onugem.GemPorts {
1751 // If the gemport is found, delete it from local cache.
1752 if gem == gemPortID {
1753 onugem.GemPorts = append(onugem.GemPorts[:j], onugem.GemPorts[j+1:]...)
1754 f.onuGemInfoLock.Lock()
1755 f.onuGemInfoMap[onuID] = onugem
1756 f.onuGemInfoLock.Unlock()
1757 logger.Infow(ctx, "removed-gemport-from-local-cache",
1758 log.Fields{
1759 "intf-id": intfID,
1760 "onu-id": onuID,
1761 "deletedgemport-id": gemPortID,
1762 "gemports": onugem.GemPorts,
1763 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001764 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301765 }
1766 }
1767}
1768
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301769//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001770// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001771func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Girish Gowdra82c80982021-03-26 16:22:02 -07001772 gemPortID int32, flowID uint64, portNum uint32, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001773
Girish Gowdraa482f272021-03-24 23:04:19 -07001774 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
1775 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001776 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1777 log.Fields{
1778 "tpPath": tpPath,
1779 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001780
1781 used := f.isGemPortUsedByAnotherFlow(uint32(gemPortID))
1782
1783 if used {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001784 f.gemToFlowIDsKey.RLock()
1785 flowIDs := f.gemToFlowIDs[uint32(gemPortID)]
1786 f.gemToFlowIDsKey.RUnlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001787
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001788 for i, flowIDinMap := range flowIDs {
1789 if flowIDinMap == flowID {
1790 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001791 f.gemToFlowIDsKey.Lock()
1792 f.gemToFlowIDs[uint32(gemPortID)] = flowIDs
1793 f.gemToFlowIDsKey.Unlock()
1794 // everytime gemToFlowIDs cache is updated the same should be updated
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001795 // in kv store by calling UpdateFlowIDsForGem
Girish Gowdraa482f272021-03-24 23:04:19 -07001796 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, intfID, uint32(gemPortID), flowIDs); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001797 return err
1798 }
1799 break
1800 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001801 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001802 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1803 log.Fields{
1804 "gemport-id": gemPortID,
1805 "usedByFlows": flowIDs,
1806 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -07001807
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001808 return nil
1809 }
1810 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 -07001811 f.deleteGemPortFromLocalCache(ctx, intfID, uint32(onuID), uint32(gemPortID))
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001812 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, intfID, uint32(onuID), uint32(gemPortID)) // ignore error and proceed.
1813 //everytime an entry is deleted from gemToFlowIDs cache, the same should be updated in kv as well
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001814 // by calling DeleteFlowIDsForGem
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001815 f.gemToFlowIDsKey.Lock()
1816 delete(f.gemToFlowIDs, uint32(gemPortID))
1817 f.gemToFlowIDsKey.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001818
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001819 f.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, uint32(gemPortID))
1820
1821 f.resourceMgr.FreeGemPortID(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001822
Mahir Gunyel199570a2021-07-04 15:39:36 -07001823 //First remove TCONT from child if needed. Then remove the GEM.
1824 //It is expected from child to clean ani side conf if all GEMs of TP are deleted.
1825 //Before this, ensure that the related TCONT deletions are informed to child.
1826 //Refer to VOL-4215.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001827 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1828 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1829 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1830 log.Fields{
1831 "tp-id": tpID,
1832 "path": tpPath}, err)
1833 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001834 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001835 case *tp_pb.TechProfileInstance:
Gamze Abakacb0e6772021-06-10 08:32:12 +00001836 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst, uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001837 if !ok {
Girish Gowdraa482f272021-03-24 23:04:19 -07001838 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); 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.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001842 logger.Warn(ctx, err)
1843 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001844 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 -07001845 logger.Warn(ctx, err)
1846 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001847 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 -07001848 logger.Warn(ctx, err)
1849 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001850 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001851 case *tp_pb.EponTechProfileInstance:
Girish Gowdraa482f272021-03-24 23:04:19 -07001852 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001853 logger.Warn(ctx, err)
1854 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001855 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001856 logger.Warn(ctx, err)
1857 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001858 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001859 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001860 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001861 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05301862 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07001863 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05301864 "onu-id": onuID,
1865 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001866 "device-id": f.deviceHandler.device.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001867 "alloc-id": techprofileInst.AllocId})
Gamze Abakafee36392019-10-03 11:17:24 +00001868 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001869 default:
1870 logger.Errorw(ctx, "error-unknown-tech",
1871 log.Fields{
1872 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001873 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001874
Mahir Gunyel199570a2021-07-04 15:39:36 -07001875 // Delete the gem port on the ONU. Send Gem Removal After TCONT removal.
1876 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
1877 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
1878 log.Fields{
1879 "err": err,
1880 "intfID": intfID,
1881 "onu-id": onuID,
1882 "uni-id": uniID,
1883 "device-id": f.deviceHandler.device.Id,
1884 "gemport-id": gemPortID})
1885 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301886 return nil
1887}
1888
David K. Bainbridge794735f2020-02-11 21:01:37 -08001889// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07001890func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001891 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05301892 log.Fields{
1893 "flowDirection": flowDirection,
1894 "flow": *flow,
1895 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001896
1897 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001898 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00001899 }
1900
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301901 classifierInfo := make(map[string]interface{})
1902
Neha Sharma96b7bf22020-06-15 10:37:32 +00001903 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301904 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001905 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001906 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301907 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301908
David K. Bainbridge794735f2020-02-11 21:01:37 -08001909 onuID := int32(onu)
1910 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001911 tpID, err := getTpIDFromFlow(ctx, flow)
1912 if err != nil {
1913 return olterrors.NewErrNotFound("tp-id",
1914 log.Fields{
1915 "flow": flow,
1916 "intf-id": Intf,
1917 "onu-id": onuID,
1918 "uni-id": uniID,
1919 "device-id": f.deviceHandler.device.Id}, err)
1920 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301921
1922 for _, field := range flows.GetOfbFields(flow) {
1923 if field.Type == flows.IP_PROTO {
1924 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00001925 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301926 }
1927 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001928 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05301929 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001930 "flow-id": flow.Id,
1931 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05301932 "onu-id": onuID,
1933 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301934
1935 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1936 onuID = -1
1937 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00001938 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
1939 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001940 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001941 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001942 log.Fields{
1943 "port-number": inPort,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001944 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001945 return err
David K. Bainbridge794735f2020-02-11 21:01:37 -08001946 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301947 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001948
1949 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
1950 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001951 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
1952 return err
1953 }
Girish Gowdra82c80982021-03-26 16:22:02 -07001954
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001955 f.flowIDToGemsLock.Lock()
1956 gems, ok := f.flowIDToGems[flow.Id]
1957 if !ok {
1958 logger.Errorw(ctx, "flow-id-to-gem-map-not-found", log.Fields{"flowID": flow.Id})
1959 f.flowIDToGemsLock.Unlock()
1960 return olterrors.NewErrNotFound("flow-id-to-gem-map-not-found", log.Fields{"flowID": flow.Id}, nil)
1961 }
1962 copyOfGems := make([]uint32, len(gems))
1963 _ = copy(copyOfGems, gems)
1964 // Delete the flow-id to gemport list entry from the map now the flow is deleted.
1965 delete(f.flowIDToGems, flow.Id)
1966 f.flowIDToGemsLock.Unlock()
1967
1968 logger.Debugw(ctx, "gems-to-be-cleared", log.Fields{"gems": copyOfGems})
1969 for _, gem := range copyOfGems {
1970 if err = f.clearResources(ctx, Intf, onuID, uniID, int32(gem), flow.Id, portNum, tpID); err != nil {
Girish Gowdra0aca4982021-01-04 12:44:27 -08001971 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001972 "flow-id": flow.Id,
1973 "device-id": f.deviceHandler.device.Id,
1974 "onu-id": onuID,
1975 "intf": Intf,
1976 "gem": gem,
1977 "err": err,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001978 })
1979 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301980 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301981 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001982
Girish Gowdra82c80982021-03-26 16:22:02 -07001983 // Decrement reference count for the meter associated with the given <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
1984 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, Intf, uint32(onuID), uint32(uniID), tpID, false); err != nil {
1985 return err
1986 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001987 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001988}
1989
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001990//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07001991func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001992
Matteo Scandolof16389e2021-05-18 00:47:08 +00001993 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301994 var direction string
1995 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001996
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301997 for _, action := range flows.GetActions(flow) {
1998 if action.Type == flows.OUTPUT {
1999 if out := action.GetOutput(); out != nil {
2000 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002001 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302002 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002003 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002004 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002005 }
2006 }
2007 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002008
2009 if flows.HasGroup(flow) {
2010 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002011 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Esin Karamanccb714b2019-11-29 15:02:06 +00002012 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302013 direction = Upstream
2014 } else {
2015 direction = Downstream
2016 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302017
Girish Gowdracefae192020-03-19 18:14:10 -07002018 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002019 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002020
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002021 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002022}
2023
Esin Karamanae41e2b2019-12-17 18:13:13 +00002024//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2025func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2026 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2027 if ethType, ok := classifierInfo[EthType]; ok {
2028 if ethType.(uint32) == IPv4EthType {
2029 if ipProto, ok := classifierInfo[IPProto]; ok {
2030 if ipProto.(uint32) == IgmpProto {
2031 return true
2032 }
2033 }
2034 }
2035 }
2036 }
2037 return false
2038}
2039
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002040// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
2041func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *voltha.OfpFlowStats, addFlow bool, flowMetadata *voltha.FlowMetadata) error {
2042 // Step1 : Fill flowControlBlock
2043 // Step2 : Push the flowControlBlock to ONU channel
2044 // Step3 : Wait on response channel for response
2045 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002046 startTime := time.Now()
2047 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002048 errChan := make(chan error)
2049 flowCb := flowControlBlock{
2050 ctx: ctx,
2051 addFlow: addFlow,
2052 flow: flow,
2053 flowMetadata: flowMetadata,
2054 errChan: &errChan,
2055 }
2056 inPort, outPort := getPorts(flow)
2057 var onuID uint32
2058 if inPort != InvalidPort && outPort != InvalidPort {
2059 _, _, onuID, _ = ExtractAccessFromFlow(inPort, outPort)
2060 }
2061 // inPort or outPort is InvalidPort for trap-from-nni flows.
2062 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2063 // Send the flowCb on the ONU flow channel
2064 f.incomingFlows[onuID] <- flowCb
2065 // Wait on the channel for flow handlers return value
2066 err := <-errChan
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002067 logger.Infow(ctx, "process-flow--received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002068 return err
2069}
2070
2071// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2072// Each incoming flow is processed in a synchronous manner, i.e., the flow is processed to completion before picking another
2073func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(subscriberFlowChannel chan flowControlBlock) {
2074 for {
2075 // block on the channel to receive an incoming flow
2076 // process the flow completely before proceeding to handle the next flow
2077 flowCb := <-subscriberFlowChannel
2078 if flowCb.addFlow {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002079 logger.Info(flowCb.ctx, "adding-flow-start")
2080 startTime := time.Now()
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002081 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002082 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002083 // Pass the return value over the return channel
2084 *flowCb.errChan <- err
2085 } else {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002086 logger.Info(flowCb.ctx, "removing-flow-start")
2087 startTime := time.Now()
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002088 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002089 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002090 // Pass the return value over the return channel
2091 *flowCb.errChan <- err
2092 }
2093 }
2094}
2095
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002096// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302097// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002098func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002099 classifierInfo := make(map[string]interface{})
2100 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002101 var UsMeterID uint32
2102 var DsMeterID uint32
2103
Neha Sharma96b7bf22020-06-15 10:37:32 +00002104 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302105 log.Fields{
2106 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002107 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002108 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002109
Neha Sharma96b7bf22020-06-15 10:37:32 +00002110 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002111 if err != nil {
2112 // Error logging is already done in the called function
2113 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002114 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302115 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002116
Esin Karamanccb714b2019-11-29 15:02:06 +00002117 if flows.HasGroup(flow) {
2118 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002119 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002120 }
2121
manikkaraj k17652a72019-05-06 09:06:36 -04002122 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002123 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002124 if err != nil {
2125 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002126 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002127 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002128
Neha Sharma96b7bf22020-06-15 10:37:32 +00002129 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302130 log.Fields{
2131 "classifierinfo_inport": classifierInfo[InPort],
2132 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002133 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002134
Humera Kouser94d7a842019-08-25 19:04:32 -04002135 if ethType, ok := classifierInfo[EthType]; ok {
2136 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002137 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002138 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002139 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002140 if ethType.(uint32) == PPPoEDEthType {
2141 if voltha.Port_ETHERNET_NNI == IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
2142 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2143 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2144 }
2145 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002146 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002147 if ipProto, ok := classifierInfo[IPProto]; ok {
2148 if ipProto.(uint32) == IPProtoDhcp {
2149 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302150 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002151 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002152 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002153 }
2154 }
2155 }
2156 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002157 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002158 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002159 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002160 }
A R Karthick1f85b802019-10-11 05:06:05 +00002161
npujarec5762e2020-01-01 14:08:48 +05302162 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002163 // also update flowmgr cache
2164 f.onuGemInfoLock.Lock()
2165 onugem, ok := f.onuGemInfoMap[onuID]
2166 if ok {
2167 found := false
2168 for _, uni := range onugem.UniPorts {
2169 if uni == portNo {
2170 found = true
2171 break
2172 }
2173 }
2174 if !found {
2175 onugem.UniPorts = append(onugem.UniPorts, portNo)
2176 f.onuGemInfoMap[onuID] = onugem
2177 logger.Infow(ctx, "added uni port to onugem cache", log.Fields{"uni": portNo})
2178 }
2179 }
2180 f.onuGemInfoLock.Unlock()
A R Karthick1f85b802019-10-11 05:06:05 +00002181
Neha Sharma96b7bf22020-06-15 10:37:32 +00002182 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002183 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302184 return olterrors.NewErrNotFound("tpid-for-flow",
2185 log.Fields{
2186 "flow": flow,
2187 "intf-id": IntfID,
2188 "onu-id": onuID,
2189 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002190 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002191 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302192 log.Fields{
2193 "tp-id": TpID,
2194 "intf-id": intfID,
2195 "onu-id": onuID,
2196 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002197 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002198 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002199 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002200 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002201 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002202 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002203
2204 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002205 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002206}
Girish Gowdra3d633032019-12-10 16:37:05 +05302207
Esin Karamanccb714b2019-11-29 15:02:06 +00002208// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002209func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002210 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002211 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302212 "classifier-info": classifierInfo,
2213 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002214
Esin Karaman65409d82020-03-18 10:58:18 +00002215 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002216 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002217 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002218 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002219
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002220 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002221
David K. Bainbridge794735f2020-02-11 21:01:37 -08002222 onuID := NoneOnuID
2223 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002224
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002225 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002226 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002227 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002228 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002229 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2230 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002231 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002232 }
2233 groupID := actionInfo[GroupID].(uint32)
2234 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002235 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002236 FlowType: Multicast,
2237 NetworkIntfId: int32(networkInterfaceID),
2238 GroupId: groupID,
2239 Classifier: classifierProto,
2240 Priority: int32(flow.Priority),
2241 Cookie: flow.Cookie}
2242
Kent Hagermane6ff1012020-07-14 15:07:53 -04002243 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002244 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002245 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002246 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002247 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002248 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002249 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002250 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002251 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002252 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002253 //cached group can be removed now
2254 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002255 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002256 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002257 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002258
David K. Bainbridge794735f2020-02-11 21:01:37 -08002259 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002260}
2261
Esin Karaman65409d82020-03-18 10:58:18 +00002262//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2263func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2264 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002265 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002266 if err != nil {
2267 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2268 }
2269 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002270 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002271
2272 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2273 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002274}
2275
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002276//sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002277func (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 -07002278
Neha Sharma96b7bf22020-06-15 10:37:32 +00002279 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302280 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002281 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302282 log.Fields{
2283 "intf-id": intfID,
2284 "onu-id": onuID,
2285 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002286 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302287 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002288 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002289
Neha Sharma96b7bf22020-06-15 10:37:32 +00002290 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002291 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{
2292 UniId: uniID,
2293 TpInstancePath: tpPath,
2294 TechTpInstance: &ic.InterAdapterTechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
2295 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002296 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002297 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
manikkaraj k17652a72019-05-06 09:06:36 -04002298 tpDownloadMsg,
2299 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03002300 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002301 onuDev.deviceType,
2302 onuDev.deviceID,
2303 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002304 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302305 return olterrors.NewErrCommunication("send-techprofile-download-request",
2306 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03002307 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05302308 "to-adapter": onuDev.deviceType,
2309 "onu-id": onuDev.deviceID,
2310 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002311 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002312 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302313 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302314}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002315
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302316//UpdateOnuInfo function adds onu info to cache and kvstore
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002317//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002318func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302319
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002320 f.onuGemInfoLock.RLock()
2321 _, ok := f.onuGemInfoMap[onuID]
2322 f.onuGemInfoLock.RUnlock()
Girish Gowdra9602eb42020-09-09 15:50:39 -07002323 // If the ONU already exists in onuGemInfo list, nothing to do
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002324 if ok {
2325 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2326 log.Fields{"onuID": onuID,
2327 "serialNum": serialNum})
2328 return nil
Girish Gowdra9602eb42020-09-09 15:50:39 -07002329 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002330
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002331 onuGemInfo := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2332 f.onuGemInfoLock.Lock()
2333 f.onuGemInfoMap[onuID] = &onuGemInfo
2334 f.onuGemInfoLock.Unlock()
2335 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onuID, onuGemInfo); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002336 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302337 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002338 logger.Infow(ctx, "updated-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302339 log.Fields{
2340 "intf-id": intfID,
2341 "onu-id": onuID,
2342 "serial-num": serialNum,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002343 "onu": onuGemInfo,
Shrey Baid26912972020-04-16 21:02:31 +05302344 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002345 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002346}
2347
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302348//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302349func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002350
Neha Sharma96b7bf22020-06-15 10:37:32 +00002351 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302352 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002353 "gem-port-id": gemPort,
2354 "intf-id": intfID,
2355 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002356 "device-id": f.deviceHandler.device.Id})
2357 f.onuGemInfoLock.RLock()
2358 onugem, ok := f.onuGemInfoMap[onuID]
2359 f.onuGemInfoLock.RUnlock()
2360 if !ok {
2361 logger.Warnw(ctx, "onu gem info is missing", log.Fields{
2362 "gem-port-id": gemPort,
2363 "intf-id": intfID,
2364 "onu-id": onuID,
2365 "device-id": f.deviceHandler.device.Id})
2366 return
2367 }
2368
2369 if onugem.OnuID == onuID {
2370 // check if gem already exists , else update the cache and kvstore
2371 for _, gem := range onugem.GemPorts {
2372 if gem == gemPort {
2373 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
2374 log.Fields{
2375 "gem": gemPort,
2376 "device-id": f.deviceHandler.device.Id})
2377 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302378 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302379 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002380 onugem.GemPorts = append(onugem.GemPorts, gemPort)
2381 f.onuGemInfoLock.Lock()
2382 f.onuGemInfoMap[onuID] = onugem
2383 f.onuGemInfoLock.Unlock()
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002384 logger.Debugw(ctx, "updated onu gem info from cache", log.Fields{"onugem": onugem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002385 } else {
2386 logger.Warnw(ctx, "mismatched onu id", log.Fields{
2387 "gem-port-id": gemPort,
2388 "intf-id": intfID,
2389 "onu-id": onuID,
2390 "device-id": f.deviceHandler.device.Id})
2391 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302392 }
npujarec5762e2020-01-01 14:08:48 +05302393 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302394 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002395 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302396 log.Fields{
2397 "intf-id": intfID,
2398 "onu-id": onuID,
2399 "gemPort": gemPort,
2400 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002401 return
2402 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002403 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302404 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002405 "gem-port-id": gemPort,
2406 "intf-id": intfID,
2407 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002408 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002409}
2410
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002411//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302412func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002413 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002414
2415 if packetIn.IntfType == "pon" {
2416 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002417 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002418 onuID, uniID := packetIn.OnuId, packetIn.UniId
2419 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 +00002420
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002421 if packetIn.PortNo != 0 {
2422 logicalPortNum = packetIn.PortNo
2423 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002424 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002425 }
2426 // 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 +00002427 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002428 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002429 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002430 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002431
2432 if logger.V(log.DebugLevel) {
2433 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2434 log.Fields{
2435 "logical-port-num": logicalPortNum,
2436 "intf-type": packetIn.IntfType,
2437 "packet": hex.EncodeToString(packetIn.Pkt),
2438 })
2439 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002440 return logicalPortNum, nil
2441}
2442
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002443//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002444func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002445 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002446
2447 ctag, priority, err := getCTagFromPacket(ctx, packet)
2448 if err != nil {
2449 return 0, err
2450 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302451
Esin Karaman7fb80c22020-07-16 14:23:33 +00002452 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002453 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002454 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002455 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002456 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302457 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002458 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302459 log.Fields{
2460 "pktinkey": pktInkey,
2461 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002462
2463 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002464 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302465 //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 +00002466 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302467 if err == nil {
2468 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002469 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302470 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002471 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002472 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302473 log.Fields{
2474 "pktinkey": pktInkey,
2475 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302476 return gemPortID, nil
2477 }
2478 }
Shrey Baid26912972020-04-16 21:02:31 +05302479 return uint32(0), olterrors.NewErrNotFound("gem-port",
2480 log.Fields{
2481 "pktinkey": pktInkey,
2482 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002483
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002484}
2485
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002486func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2487 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002488 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002489 classifier[PacketTagType] = DoubleTag
2490 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002491 /* We manage flowId resource pool on per PON port basis.
2492 Since this situation is tricky, as a hack, we pass the NNI port
2493 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002494 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002495 on NNI port, use onu_id as -1 (invalid)
2496 ****************** CAVEAT *******************
2497 This logic works if the NNI Port Id falls within the same valid
2498 range of PON Port Ids. If this doesn't work for some OLT Vendor
2499 we need to have a re-look at this.
2500 *********************************************
2501 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002502 onuID := -1
2503 uniID := -1
2504 gemPortID := -1
2505 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002506 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302507 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302508 return olterrors.NewErrNotFound("nni-intreface-id",
2509 log.Fields{
2510 "classifier": classifier,
2511 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002512 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302513 }
2514
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002515 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002516 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002517 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002518 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002519
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002520 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2521 log.Fields{
2522 "classifier": classifier,
2523 "action": action,
2524 "flowId": logicalFlow.Id,
2525 "intf-id": networkInterfaceID})
2526
David K. Bainbridge794735f2020-02-11 21:01:37 -08002527 classifierProto, err := makeOpenOltClassifierField(classifier)
2528 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002529 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002530 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002531 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002532 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002533 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002534 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002535 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002536 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002537 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2538 OnuId: int32(onuID), // OnuId not required
2539 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002540 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002541 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002542 AllocId: int32(allocID), // AllocId not used
2543 NetworkIntfId: int32(networkInterfaceID),
2544 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002545 Classifier: classifierProto,
2546 Action: actionProto,
2547 Priority: int32(logicalFlow.Priority),
2548 Cookie: logicalFlow.Cookie,
2549 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002550 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002551 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002552 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002553 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002554 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002555}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002556
Esin Karamanae41e2b2019-12-17 18:13:13 +00002557//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2558func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2559 var packetType string
2560 ovid, ivid := false, false
2561 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2562 vid := vlanID & VlanvIDMask
2563 if vid != ReservedVlan {
2564 ovid = true
2565 }
2566 }
2567 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2568 vid := uint32(metadata)
2569 if vid != ReservedVlan {
2570 ivid = true
2571 }
2572 }
2573 if ovid && ivid {
2574 packetType = DoubleTag
2575 } else if !ovid && !ivid {
2576 packetType = Untagged
2577 } else {
2578 packetType = SingleTag
2579 }
2580 return packetType
2581}
2582
2583//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002584func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002585 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002586 action := make(map[string]interface{})
2587 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2588 action[TrapToHost] = true
2589 /* We manage flowId resource pool on per PON port basis.
2590 Since this situation is tricky, as a hack, we pass the NNI port
2591 index (network_intf_id) as PON port Index for the flowId resource
2592 pool. Also, there is no ONU Id available for trapping packets
2593 on NNI port, use onu_id as -1 (invalid)
2594 ****************** CAVEAT *******************
2595 This logic works if the NNI Port Id falls within the same valid
2596 range of PON Port Ids. If this doesn't work for some OLT Vendor
2597 we need to have a re-look at this.
2598 *********************************************
2599 */
2600 onuID := -1
2601 uniID := -1
2602 gemPortID := -1
2603 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002604 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002605 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302606 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002607 "classifier": classifier,
2608 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002609 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002610 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002611 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002612 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002613 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002614 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002615
David K. Bainbridge794735f2020-02-11 21:01:37 -08002616 classifierProto, err := makeOpenOltClassifierField(classifier)
2617 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002618 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002619 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002620 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002621 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002622 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002623 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002624 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002625 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002626 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2627 OnuId: int32(onuID), // OnuId not required
2628 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002629 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002630 FlowType: Downstream,
2631 AllocId: int32(allocID), // AllocId not used
2632 NetworkIntfId: int32(networkInterfaceID),
2633 GemportId: int32(gemPortID), // GemportId not used
2634 Classifier: classifierProto,
2635 Action: actionProto,
2636 Priority: int32(logicalFlow.Priority),
2637 Cookie: logicalFlow.Cookie,
2638 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002639 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002640 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002641 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002642 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002643
David K. Bainbridge794735f2020-02-11 21:01:37 -08002644 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002645}
2646
salmansiddiqui7ac62132019-08-22 03:58:50 +00002647func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2648 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302649 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002650 }
2651 if Dir == tp_pb.Direction_UPSTREAM {
2652 return "upstream", nil
2653 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2654 return "downstream", nil
2655 }
2656 return "", nil
2657}
2658
Kent Hagermane6ff1012020-07-14 15:07:53 -04002659// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302660func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002661 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002662 tpID uint32, uni string) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002663 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002664 intfID := args[IntfID]
2665 onuID := args[OnuID]
2666 uniID := args[UniID]
2667 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002668 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002669 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002670 gemToAes := make(map[uint32]bool)
2671
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002672 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002673 var direction = tp_pb.Direction_UPSTREAM
2674 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002675 case *tp_pb.TechProfileInstance:
Gamze Abaka7650be62021-02-26 10:50:36 +00002676 if IsUpstream(actionInfo[Output].(uint32)) {
2677 attributes = TpInst.UpstreamGemPortAttributeList
2678 } else {
2679 attributes = TpInst.DownstreamGemPortAttributeList
2680 direction = tp_pb.Direction_DOWNSTREAM
2681 }
2682 default:
2683 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
2684 return
2685 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002686
2687 if len(gemPorts) == 1 {
2688 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002689 gemPortID = gemPorts[0]
2690 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002691 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2692 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002693 pBitMap := attributes[idx].PbitMap
2694 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2695 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2696 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
2697 // this pcp bit traffic.
2698 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2699 if pbitSet == pbit1 {
2700 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2701 pbitToGem[pcp] = gemID
2702 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002703 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002704 }
2705 }
2706 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002707 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2708 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2709 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002710 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002711 }
2712
Gamze Abaka7650be62021-02-26 10:50:36 +00002713 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2714 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2715
salmansiddiqui7ac62132019-08-22 03:58:50 +00002716 if ipProto, ok := classifierInfo[IPProto]; ok {
2717 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002718 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002719 "tp-id": tpID,
2720 "alloc-id": allocID,
2721 "intf-id": intfID,
2722 "onu-id": onuID,
2723 "uni-id": uniID,
2724 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002725 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002726 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002727 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002728 }
2729
Girish Gowdra32625212020-04-29 11:26:35 -07002730 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002731 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302732 log.Fields{
2733 "intf-id": intfID,
2734 "onu-id": onuID,
2735 "uni-id": uniID,
2736 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002737 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002738 logger.Warn(ctx, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002739 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002740 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002741 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002742 return
2743 }
2744 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002745 if ethType.(uint32) == EapEthType {
2746 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002747 "intf-id": intfID,
2748 "onu-id": onuID,
2749 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002750 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002751 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002752 var vlanID uint32
2753 if val, ok := classifierInfo[VlanVid]; ok {
2754 vlanID = (val.(uint32)) & VlanvIDMask
2755 } else {
2756 vlanID = DefaultMgmtVlan
2757 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002758 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002759 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002760 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002761 } else if ethType.(uint32) == PPPoEDEthType {
2762 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2763 "tp-id": tpID,
2764 "alloc-id": allocID,
2765 "intf-id": intfID,
2766 "onu-id": onuID,
2767 "uni-id": uniID,
2768 })
2769 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002770 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002771 logger.Warn(ctx, err)
2772 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002773 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002774 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002775 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002776 "intf-id": intfID,
2777 "onu-id": onuID,
2778 "uni-id": uniID,
2779 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002780 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002781 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002782 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002783 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002784 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002785 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002786 "intf-id": intfID,
2787 "onu-id": onuID,
2788 "uni-id": uniID,
2789 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002790 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002791 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002792 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002793 }
2794 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002795 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05302796 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002797 "intf-id": intfID,
2798 "onu-id": onuID,
2799 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05302800 "classifier": classifierInfo,
2801 "action": actionInfo,
2802 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002803 return
2804 }
2805 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002806 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002807 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002808 logger.Warn(ctx, err)
2809 }
2810 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002811}
2812
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002813func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002814 f.gemToFlowIDsKey.RLock()
2815 flowIDList := f.gemToFlowIDs[gemPortID]
2816 f.gemToFlowIDsKey.RUnlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002817 return len(flowIDList) > 1
2818
Gamze Abakafee36392019-10-03 11:17:24 +00002819}
2820
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002821func (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 +05302822 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002823 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2824 for _, currentGemPort := range currentGemPorts {
2825 for _, tpGemPort := range tpGemPorts {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002826 if (currentGemPort == tpGemPort.GemportId) && (currentGemPort != gemPortID) {
Gamze Abakafee36392019-10-03 11:17:24 +00002827 return true, currentGemPort
2828 }
2829 }
2830 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00002831 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
2832 return false, 0
2833}
Girish Gowdra54934262019-11-13 14:19:55 +05302834
Gamze Abakacb0e6772021-06-10 08:32:12 +00002835func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002836 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
2837 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
2838 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 +00002839 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05302840 for i := 0; i < len(tpInstances); i++ {
2841 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00002842 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002843 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Gamze Abakacb0e6772021-06-10 08:32:12 +00002844 logger.Debugw(ctx, "alloc-is-in-use",
2845 log.Fields{
2846 "device-id": f.deviceHandler.device.Id,
2847 "intfID": sq.intfID,
2848 "onuID": sq.onuID,
2849 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002850 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00002851 })
2852 return true
Girish Gowdra54934262019-11-13 14:19:55 +05302853 }
2854 }
2855 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00002856 return false
Gamze Abakafee36392019-10-03 11:17:24 +00002857}
2858
Neha Sharma96b7bf22020-06-15 10:37:32 +00002859func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002860 for _, field := range flows.GetOfbFields(flow) {
2861 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002862 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002863 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002864 } else if field.Type == flows.ETH_DST {
2865 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002866 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07002867 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002868 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002869 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002870 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002871 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002872 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002873 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05302874 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00002875 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002876 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002877 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002878 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002879 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002880 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002881 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002882 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002883 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002884 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002885 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002886 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002887 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002888 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002889 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002890 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002891 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002892 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002893 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07002894 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002895 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002896 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002897 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002898 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002899 return
2900 }
2901 }
2902}
2903
Neha Sharma96b7bf22020-06-15 10:37:32 +00002904func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07002905 for _, action := range flows.GetActions(flow) {
2906 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002907 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002908 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002909 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002910 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002911 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002912 }
Scott Baker355d1742019-10-24 10:57:52 -07002913 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002914 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00002915 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002916 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002917 if out := action.GetPush(); out != nil {
2918 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002919 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002920 } else {
2921 actionInfo[PushVlan] = true
2922 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00002923 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05302924 log.Fields{
2925 "push-tpid": actionInfo[TPID].(uint32),
2926 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002927 }
2928 }
Scott Baker355d1742019-10-24 10:57:52 -07002929 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002930 if out := action.GetSetField(); out != nil {
2931 if field := out.GetField(); field != nil {
2932 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00002933 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002934 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002935 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
2936 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002937 }
2938 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002939 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002940 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002941 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002942 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002943 }
2944 }
2945 return nil
2946}
2947
Neha Sharma96b7bf22020-06-15 10:37:32 +00002948func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00002949 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00002950 fieldtype := ofbField.GetType()
2951 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00002952 if vlan := ofbField.GetVlanVid(); vlan != 0 {
2953 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00002954 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002955 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002956 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00002957 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00002958 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
2959 pcp := ofbField.GetVlanPcp()
2960 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002961 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002962 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002963 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00002964 }
2965 }
2966}
2967
Neha Sharma96b7bf22020-06-15 10:37:32 +00002968func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00002969 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002970 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00002971 } else {
2972 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00002973 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002974 }
2975}
2976
Neha Sharma96b7bf22020-06-15 10:37:32 +00002977func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002978 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002979 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002980 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2981 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002982 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002983 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00002984 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05302985 log.Fields{
2986 "newinport": classifierInfo[InPort].(uint32),
2987 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002988 } else {
Shrey Baid26912972020-04-16 21:02:31 +05302989 return olterrors.NewErrNotFound("child-in-port",
2990 log.Fields{
2991 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
2992 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002993 }
2994 }
2995 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002996 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002997 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07002998 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002999 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003000 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003001 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303002 log.Fields{
3003 "newoutport": actionInfo[Output].(uint32),
3004 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003005 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303006 return olterrors.NewErrNotFound("out-port",
3007 log.Fields{
3008 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3009 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003010 }
3011 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3012 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003013 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003014 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003015 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303016 log.Fields{
3017 "newinport": actionInfo[Output].(uint32),
3018 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003019 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303020 return olterrors.NewErrNotFound("nni-port",
3021 log.Fields{
3022 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3023 "in-port": classifierInfo[InPort].(uint32),
3024 "out-port": actionInfo[Output].(uint32),
3025 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003026 }
3027 }
3028 }
3029 return nil
3030}
Gamze Abakafee36392019-10-03 11:17:24 +00003031
Neha Sharma96b7bf22020-06-15 10:37:32 +00003032func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003033 /* Metadata 8 bytes:
3034 Most Significant 2 Bytes = Inner VLAN
3035 Next 2 Bytes = Tech Profile ID(TPID)
3036 Least Significant 4 Bytes = Port ID
3037 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3038 subscriber related flows.
3039 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003040 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003041 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003042 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003043 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003044 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003045 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003046}
3047
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003048func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3049 for _, sliceElement := range slice {
3050 if sliceElement == item {
3051 return slice
3052 }
3053 }
3054 return append(slice, item)
3055}
3056
3057func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003058 for _, sliceElement := range slice {
3059 if sliceElement == item {
3060 return slice
3061 }
3062 }
3063 return append(slice, item)
3064}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303065
3066// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003067func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303068
3069 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3070 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003071 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003072 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003073 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003074 log.Fields{
3075 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003076 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003077 return uint32(0), err
3078 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003079 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303080 return intfID, nil
3081 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003082 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003083 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003084 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003085 log.Fields{
3086 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003087 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003088 return uint32(0), err
3089 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003090 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303091 return intfID, nil
3092 }
3093 return uint32(0), nil
3094}
3095
3096// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003097func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3098 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3099 if err != nil {
3100 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3101 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3102 return
3103 }
3104 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003105
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003106 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003107 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003108 f.packetInGemPortLock.RUnlock()
3109
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303110 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003111 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003112 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 +05303113 log.Fields{
3114 "pktinkey": pktInkey,
3115 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003116 return
3117 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303118 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003119 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003120 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003121 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003122
npujarec5762e2020-01-01 14:08:48 +05303123 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003124 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 +05303125 log.Fields{
3126 "pktinkey": pktInkey,
3127 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303128}
3129
Esin Karaman7fb80c22020-07-16 14:23:33 +00003130//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3131func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3132 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003133 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003134 return 0, 0, errors.New("invalid packet length")
3135 }
3136 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3137 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3138
3139 var index int8
3140 if outerEthType == 0x8100 {
3141 if innerEthType == 0x8100 {
3142 // q-in-q 802.1ad or 802.1q double tagged packet.
3143 // get the inner vlanId
3144 index = 18
3145 } else {
3146 index = 14
3147 }
3148 priority := (packet[index] >> 5) & 0x7
3149 //13 bits composes vlanId value
3150 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3151 return vlan, priority, nil
3152 }
3153 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3154 return 0, 0, nil
3155}
3156
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003157func (f *OpenOltFlowMgr) loadFlowIDsForGemAndGemIDsForFlow(ctx context.Context) {
3158 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - start")
3159 f.onuGemInfoLock.RLock()
3160 f.gemToFlowIDsKey.Lock()
3161 f.flowIDToGemsLock.Lock()
3162 for _, og := range f.onuGemInfoMap {
3163 for _, gem := range og.GemPorts {
3164 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, f.ponPortIdx, gem)
3165 if err != nil {
3166 f.gemToFlowIDs[gem] = flowIDs
3167 for _, flowID := range flowIDs {
3168 if _, ok := f.flowIDToGems[flowID]; !ok {
3169 f.flowIDToGems[flowID] = []uint32{gem}
3170 } else {
3171 f.flowIDToGems[flowID] = appendUnique32bit(f.flowIDToGems[flowID], gem)
3172 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303173 }
3174 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303175 }
3176 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003177 f.flowIDToGemsLock.Unlock()
3178 f.gemToFlowIDsKey.Unlock()
3179 f.onuGemInfoLock.RUnlock()
3180 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - end")
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303181}
Esin Karamanccb714b2019-11-29 15:02:06 +00003182
Girish Gowdra9602eb42020-09-09 15:50:39 -07003183//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3184// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003185func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003186 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003187 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3188 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003189 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003190 "flow-id": flow.Id,
3191 "device-id": f.deviceHandler.device.Id})
3192 // Remove from device
3193 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3194 // DKB
3195 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3196 log.Fields{
3197 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003198 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003199 return err
3200 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003201
3202 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003203}
3204
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003205func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, ponID uint32, onuID uint32, uniID uint32) *ic.InterAdapterTechProfileDownloadMessage {
3206 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003207 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003208 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
3209 return nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003210 }
3211
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003212 switch tpInst := tpInst.(type) {
3213 case *tp_pb.TechProfileInstance:
3214 logger.Debugw(ctx, "fetched-tp-instance-successfully--formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
3215 return &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID,
3216 TpInstancePath: tpPath,
3217 TechTpInstance: &ic.InterAdapterTechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003218 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003219 case *openoltpb2.EponTechProfileInstance:
3220 return &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID,
3221 TpInstancePath: tpPath,
3222 TechTpInstance: &ic.InterAdapterTechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
3223 }
3224 default:
3225 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003226 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003227 return nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003228}
3229
Girish Gowdrabcf98af2021-07-01 08:24:42 -07003230func (f *OpenOltFlowMgr) getOnuGemInfoList(ctx context.Context) []rsrcMgr.OnuGemInfo {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003231 var onuGemInfoLst []rsrcMgr.OnuGemInfo
3232 f.onuGemInfoLock.RLock()
3233 defer f.onuGemInfoLock.RUnlock()
3234 for _, v := range f.onuGemInfoMap {
3235 onuGemInfoLst = append(onuGemInfoLst, *v)
3236 }
3237 return onuGemInfoLst
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003238}