blob: 978cea895d437c302d60f7174c511ec33fe41b96 [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"
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070025 "github.com/opencord/voltha-lib-go/v5/pkg/meters"
Gamze Abaka7650be62021-02-26 10:50:36 +000026 "strconv"
serkant.uluderya4aff1862020-09-17 23:35:26 +030027 "strings"
28 "sync"
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070029 "time"
serkant.uluderya4aff1862020-09-17 23:35:26 +030030
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070031 "github.com/opencord/voltha-lib-go/v5/pkg/flows"
32 "github.com/opencord/voltha-lib-go/v5/pkg/log"
33 tp "github.com/opencord/voltha-lib-go/v5/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080034 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070035 "github.com/opencord/voltha-protos/v4/go/common"
36 ic "github.com/opencord/voltha-protos/v4/go/inter_container"
37 ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
38 openoltpb2 "github.com/opencord/voltha-protos/v4/go/openolt"
39 tp_pb "github.com/opencord/voltha-protos/v4/go/tech_profile"
40 "github.com/opencord/voltha-protos/v4/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040041
Thomas Lee S94109f12020-03-03 16:39:29 +053042 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000043 "google.golang.org/grpc/codes"
44 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053045)
46
47const (
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070048 //IPProtoDhcp flow category
49 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053050
Girish Gowdraa09aeab2020-09-14 16:30:52 -070051 //IgmpProto proto value
52 IgmpProto = 2
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070053
54 //EapEthType eapethtype value
55 EapEthType = 0x888e
56 //LldpEthType lldp ethtype value
57 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000058 //IPv4EthType IPv4 ethernet type value
59 IPv4EthType = 0x800
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -030060 //PPPoEDEthType PPPoE discovery ethernet type value
61 PPPoEDEthType = 0x8863
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070062
Andrea Campanella7acc0b92020-02-14 09:20:49 +010063 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
64 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040065
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070066 //DefaultMgmtVlan default vlan value
67 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053068
manikkaraj kbf256be2019-03-25 00:13:48 +053069 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070070
David K. Bainbridge82efc492019-09-04 09:57:11 -070071 //Upstream constant
72 Upstream = "upstream"
73 //Downstream constant
74 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000075 //Multicast constant
76 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070077 //PacketTagType constant
78 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070079 //Untagged constant
80 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070081 //SingleTag constant
82 SingleTag = "single_tag"
83 //DoubleTag constant
84 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053085
86 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070087
88 //EthType constant
89 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +000090 //EthDst constant
91 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070092 //TPID constant
93 TPID = "tpid"
94 //IPProto constant
95 IPProto = "ip_proto"
96 //InPort constant
97 InPort = "in_port"
98 //VlanVid constant
99 VlanVid = "vlan_vid"
100 //VlanPcp constant
101 VlanPcp = "vlan_pcp"
102
103 //UDPDst constant
104 UDPDst = "udp_dst"
105 //UDPSrc constant
106 UDPSrc = "udp_src"
107 //Ipv4Dst constant
108 Ipv4Dst = "ipv4_dst"
109 //Ipv4Src constant
110 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700111 //Metadata constant
112 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700113 //TunnelID constant
114 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700115 //Output constant
116 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000117 //GroupID constant
118 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700119 // Actions
120
121 //PopVlan constant
122 PopVlan = "pop_vlan"
123 //PushVlan constant
124 PushVlan = "push_vlan"
125 //TrapToHost constant
126 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400127 //MaxMeterBand constant
128 MaxMeterBand = 2
129 //VlanPCPMask contant
130 VlanPCPMask = 0xFF
131 //VlanvIDMask constant
132 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000133 //IntfID constant
134 IntfID = "intfId"
135 //OnuID constant
136 OnuID = "onuId"
137 //UniID constant
138 UniID = "uniId"
139 //PortNo constant
140 PortNo = "portNo"
141 //AllocID constant
142 AllocID = "allocId"
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000143 //GemID constant
144 GemID = "gemId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000145
146 //NoneOnuID constant
147 NoneOnuID = -1
148 //NoneUniID constant
149 NoneUniID = -1
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700150
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700151 // Max number of flows that can be queued per ONU
152 maxConcurrentFlowsPerOnu = 20
manikkaraj kbf256be2019-03-25 00:13:48 +0530153
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700154 bitMapPrefix = "0b"
155 pbit1 = '1'
156)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400157
Gamze Abakafee36392019-10-03 11:17:24 +0000158type schedQueue struct {
159 direction tp_pb.Direction
160 intfID uint32
161 onuID uint32
162 uniID uint32
163 tpID uint32
164 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700165 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000166 meterID uint32
167 flowMetadata *voltha.FlowMetadata
168}
169
Gamze Abaka7650be62021-02-26 10:50:36 +0000170type flowContext struct {
171 intfID uint32
172 onuID uint32
173 uniID uint32
174 portNo uint32
175 classifier map[string]interface{}
176 action map[string]interface{}
177 logicalFlow *ofp.OfpFlowStats
178 allocID uint32
179 gemPortID uint32
180 tpID uint32
181 pbitToGem map[uint32]uint32
182 gemToAes map[uint32]bool
183}
184
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700185// This control block is created per flow add/remove and pushed on the incomingFlows channel slice
186// The flowControlBlock is then picked by the perOnuFlowHandlerRoutine for further processing.
187// There is on perOnuFlowHandlerRoutine routine per ONU that constantly monitors for any incoming
188// flow and processes it serially
189type flowControlBlock struct {
190 ctx context.Context // Flow handler context
191 addFlow bool // if true flow to be added, else removed
192 flow *voltha.OfpFlowStats // Flow message
193 flowMetadata *voltha.FlowMetadata // FlowMetadata that contains flow meter information. This can be nil for Flow remove
194 errChan *chan error // channel to report the Flow handling error
Esin Karamanccb714b2019-11-29 15:02:06 +0000195}
196
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700197//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530198type OpenOltFlowMgr struct {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700199 ponPortIdx uint32 // Pon Port this FlowManager is responsible for
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700200 techprofile tp.TechProfileIf
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700201 deviceHandler *DeviceHandler
202 grpMgr *OpenOltGroupMgr
203 resourceMgr *rsrcMgr.OpenOltResourceMgr
204
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700205 gemToFlowIDs map[uint32][]uint64 // gem port id to flow ids
206 gemToFlowIDsKey sync.RWMutex // lock to be used to access the gemToFlowIDs map
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700207
208 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
209 packetInGemPortLock sync.RWMutex
210
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700211 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700212 onuGemInfoMap map[uint32]*rsrcMgr.OnuGemInfo //onu, gem and uni info local cache -> map of onuID to OnuGemInfo
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700213 // We need to have a global lock on the onuGemInfo map
Girish Gowdra9602eb42020-09-09 15:50:39 -0700214 onuGemInfoLock sync.RWMutex
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700215
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700216 flowIDToGems map[uint64][]uint32
217 flowIDToGemsLock sync.RWMutex
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700218
219 // Slice of channels. Each channel in slice, index by ONU ID, queues flows per ONU.
220 // A go routine per ONU, waits on the unique channel (indexed by ONU ID) for incoming flows (add/remove)
221 incomingFlows []chan flowControlBlock
manikkaraj kbf256be2019-03-25 00:13:48 +0530222}
223
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700224//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700225func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000226 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530227 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530228 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530229
manikkaraj kbf256be2019-03-25 00:13:48 +0530230 flowMgr.deviceHandler = dh
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700231 flowMgr.ponPortIdx = ponPortIdx
Girish Gowdra9602eb42020-09-09 15:50:39 -0700232 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530233 flowMgr.resourceMgr = rMgr
Neha Sharma96b7bf22020-06-15 10:37:32 +0000234 if err = flowMgr.populateTechProfilePerPonPort(ctx); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700235 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"err": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530236 return nil
237 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700238 flowMgr.gemToFlowIDs = make(map[uint32][]uint64)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530239 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700240 flowMgr.flowIDToGems = make(map[uint64][]uint32)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700241
242 // Create a slice of buffered channels for handling concurrent flows per ONU.
243 // The additional entry (+1) is to handle the NNI trap flows on a separate channel from individual ONUs channel
244 flowMgr.incomingFlows = make([]chan flowControlBlock, MaxOnusPerPon+1)
245 for i := range flowMgr.incomingFlows {
246 flowMgr.incomingFlows[i] = make(chan flowControlBlock, maxConcurrentFlowsPerOnu)
247 // Spin up a go routine to handling incoming flows (add/remove).
248 // There will be on go routine per ONU.
249 // This routine will be blocked on the flowMgr.incomingFlows[onu-id] channel for incoming flows.
250 go flowMgr.perOnuFlowHandlerRoutine(flowMgr.incomingFlows[i])
251 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700252 flowMgr.onuGemInfoMap = make(map[uint32]*rsrcMgr.OnuGemInfo)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530253 //Load the onugem info cache from kv store on flowmanager start
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700254 onuIDStart := flowMgr.deviceHandler.deviceInfo.OnuIdStart
255 onuIDEnd := flowMgr.deviceHandler.deviceInfo.OnuIdEnd
256 for onuID := onuIDStart; onuID <= onuIDEnd; onuID++ {
257 // check for a valid serial number in onuGem as GetOnuGemInfo can return nil error in case of nothing found in the path.
258 onugem, err := rMgr.GetOnuGemInfo(ctx, onuID, ponPortIdx)
259 if err == nil && onugem != nil && onugem.SerialNumber != "" {
260 flowMgr.onuGemInfoMap[onuID] = onugem
261 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530262 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700263
264 //Load flowID list per gem map And gemIDs per flow per interface from the kvstore.
265 flowMgr.loadFlowIDsForGemAndGemIDsForFlow(ctx)
266
Esin Karamanccb714b2019-11-29 15:02:06 +0000267 //load interface to multicast queue map from kv store
Girish Gowdra9602eb42020-09-09 15:50:39 -0700268 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000269 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530270 return &flowMgr
271}
272
Kent Hagermane6ff1012020-07-14 15:07:53 -0400273func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700274 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
275 // 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 -0700276 return f.registerFlowIDForGemAndGemIDForFlow(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowFromCore)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700277 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
278 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
279 for _, gemPort := range deviceFlow.PbitToGemport {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700280 if err := f.registerFlowIDForGemAndGemIDForFlow(ctx, uint32(deviceFlow.AccessIntfId), gemPort, flowFromCore); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700281 return err
282 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700283 }
Gamze Abakafee36392019-10-03 11:17:24 +0000284 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700285 return nil
286}
287
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700288func (f *OpenOltFlowMgr) registerFlowIDForGemAndGemIDForFlow(ctx context.Context, accessIntfID uint32, gemPortID uint32, flowFromCore *ofp.OfpFlowStats) error {
289 // update gem->flows map
290 f.gemToFlowIDsKey.Lock()
291 flowIDList, ok := f.gemToFlowIDs[gemPortID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700292 if !ok {
293 flowIDList = []uint64{flowFromCore.Id}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700294 } else {
295 flowIDList = appendUnique64bit(flowIDList, flowFromCore.Id)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700296 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700297 f.gemToFlowIDs[gemPortID] = flowIDList
298 f.gemToFlowIDsKey.Unlock()
299
300 // update flow->gems map
301 f.flowIDToGemsLock.Lock()
302 if _, ok := f.flowIDToGems[flowFromCore.Id]; !ok {
303 f.flowIDToGems[flowFromCore.Id] = []uint32{gemPortID}
304 } else {
305 f.flowIDToGems[flowFromCore.Id] = appendUnique32bit(f.flowIDToGems[flowFromCore.Id], gemPortID)
306 }
307 f.flowIDToGemsLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700308
309 // update the flowids for a gem to the KVstore
310 return f.resourceMgr.UpdateFlowIDsForGem(ctx, accessIntfID, gemPortID, flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400311}
312
Girish Gowdra9602eb42020-09-09 15:50:39 -0700313func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000314 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
Andrea Campanellabfe08432020-09-11 17:07:03 +0200315 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000316 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530317 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700318 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530319
Neha Sharma96b7bf22020-06-15 10:37:32 +0000320 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530321 "device-id": f.deviceHandler.device.Id,
322 "intf-id": intfID,
323 "onu-id": onuID,
324 "uni-id": uniID,
325 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700326 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530327 "action": actionInfo,
328 "usmeter-iD": UsMeterID,
329 "dsmeter-iD": DsMeterID,
330 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400331 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
332 // is because the flow is an NNI flow and there would be no onu resources associated with it
333 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400334 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200335 cause := "no-onu-id-for-flow"
336 fields := log.Fields{
337 "onu": onuID,
338 "port-no": portNo,
339 "classifer": classifierInfo,
340 "action": actionInfo,
341 "device-id": f.deviceHandler.device.Id}
342 logger.Errorw(ctx, cause, fields)
343 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530344 }
345
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700346 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000347 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530348 "uni": uni,
349 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530350
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700351 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
352 "device-id": f.deviceHandler.device.Id,
353 "intf-id": intfID,
354 "onu-id": onuID,
355 "uni-id": uniID,
356 "port-no": portNo,
357 "classifier": classifierInfo,
358 "action": actionInfo,
359 "usmeter-id": UsMeterID,
360 "dsmeter-id": DsMeterID,
361 "tp-id": TpID})
362 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
363 if allocID == 0 || gemPorts == nil || TpInst == nil {
364 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
365 return olterrors.NewErrNotFound(
366 "alloc-id-gem-ports-tp-unavailable",
367 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400368 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700369 args := make(map[string]uint32)
370 args[IntfID] = intfID
371 args[OnuID] = onuID
372 args[UniID] = uniID
373 args[PortNo] = portNo
374 args[AllocID] = allocID
375
376 /* Flows can be added specific to gemport if p-bits are received.
377 * If no pbit mentioned then adding flows for all gemports
378 */
379 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
380
Andrea Campanellabfe08432020-09-11 17:07:03 +0200381 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530382}
383
salmansiddiqui7ac62132019-08-22 03:58:50 +0000384// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530385func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400386
Neha Sharma96b7bf22020-06-15 10:37:32 +0000387 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530388 log.Fields{"dir": sq.direction,
389 "intf-id": sq.intfID,
390 "onu-id": sq.onuID,
391 "uni-id": sq.uniID,
392 "tp-id": sq.tpID,
393 "meter-id": sq.meterID,
394 "tp-inst": sq.tpInst,
395 "flowmetadata": sq.flowMetadata,
396 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400397
Gamze Abakafee36392019-10-03 11:17:24 +0000398 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000399 if err != nil {
400 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400401 }
402
403 /* Lets make a simple assumption that if the meter-id is present on the KV store,
404 * then the scheduler and queues configuration is applied on the OLT device
405 * in the given direction.
406 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000407
Manikkaraj kb1d51442019-07-23 10:41:02 -0400408 var SchedCfg *tp_pb.SchedulerConfig
Girish Gowdraa482f272021-03-24 23:04:19 -0700409 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400410 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530411 return olterrors.NewErrNotFound("meter",
412 log.Fields{"intf-id": sq.intfID,
413 "onu-id": sq.onuID,
414 "uni-id": sq.uniID,
415 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400416 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000417
Girish Gowdraa482f272021-03-24 23:04:19 -0700418 if meterInfo != nil {
419 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 -0700420 if meterInfo.MeterID == sq.meterID {
Girish Gowdraa482f272021-03-24 23:04:19 -0700421 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, true); err != nil {
422 return err
423 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400424 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400425 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530426 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800427 "unsupported": "meter-id",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700428 "kv-store-meter-id": meterInfo.MeterID,
Shrey Baid26912972020-04-16 21:02:31 +0530429 "meter-id-in-flow": sq.meterID,
430 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400431 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000432
Neha Sharma96b7bf22020-06-15 10:37:32 +0000433 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530434 log.Fields{
435 "meter-id": sq.meterID,
436 "direction": Direction,
437 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000438
Gamze Abakafee36392019-10-03 11:17:24 +0000439 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700440 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Gamze Abakafee36392019-10-03 11:17:24 +0000441 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700442 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Girish Kumar8f73fe02019-12-09 13:19:37 +0000443 }
444
Girish Gowdraa482f272021-03-24 23:04:19 -0700445 found := false
446 meterInfo = &rsrcMgr.MeterInfo{}
Gamze Abakafee36392019-10-03 11:17:24 +0000447 if sq.flowMetadata != nil {
448 for _, meter := range sq.flowMetadata.Meters {
449 if sq.meterID == meter.MeterId {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700450 meterInfo.MeterID = meter.MeterId
Girish Gowdraa482f272021-03-24 23:04:19 -0700451 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 +0000452 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700453 log.Fields{"meter": meter,
Shrey Baid26912972020-04-16 21:02:31 +0530454 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -0700455 found = true
Manikkaraj kb1d51442019-07-23 10:41:02 -0400456 break
457 }
458 }
459 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000460 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400461 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700462 if !found {
Thomas Lee S94109f12020-03-03 16:39:29 +0530463 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800464 "reason": "Could-not-get-meterbands-from-flowMetadata",
465 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530466 "meter-id": sq.meterID,
467 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400468 }
Gamze Abaka01174422021-03-10 06:55:27 +0000469
470 var TrafficShaping *tp_pb.TrafficShapingInfo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700471 if TrafficShaping, err = meters.GetTrafficShapingInfo(ctx, sq.flowMetadata.Meters[0]); err != nil {
Gamze Abaka01174422021-03-10 06:55:27 +0000472 return olterrors.NewErrInvalidValue(log.Fields{
473 "reason": "invalid-meter-config",
474 "meter-id": sq.meterID,
475 "device-id": f.deviceHandler.device.Id}, nil)
476 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400477
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700478 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000479 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400480
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700481 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530482 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
483 log.Fields{"intf-id": sq.intfID,
484 "direction": sq.direction,
485 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400486 }
487
salmansiddiqui7ac62132019-08-22 03:58:50 +0000488 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400489 * store the meter id on the KV store, for further reference.
490 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700491 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 +0530492 return olterrors.NewErrAdapter("failed-updating-meter-id",
493 log.Fields{"onu-id": sq.onuID,
494 "meter-id": sq.meterID,
495 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400496 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000497 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530498 log.Fields{"direction": Direction,
Girish Gowdraa482f272021-03-24 23:04:19 -0700499 "meter-info": meterInfo,
500 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400501 return nil
502}
503
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700504func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700505 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000506
507 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530508 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
509 log.Fields{"intf-id": sq.intfID,
510 "direction": sq.direction,
511 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000512 }
513
Gamze Abakacb0e6772021-06-10 08:32:12 +0000514 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
515 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
516 log.Fields{
517 "direction": sq.direction,
518 "TrafficScheds": TrafficSched,
519 "device-id": f.deviceHandler.device.Id,
520 "intfID": sq.intfID,
521 "onuID": sq.onuID,
522 "uniID": sq.uniID})
523 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
524 IntfId: sq.intfID, OnuId: sq.onuID,
525 UniId: sq.uniID, PortNo: sq.uniPort,
526 TrafficScheds: TrafficSched}); err != nil {
527 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
528 }
529 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
530 "direction": sq.direction,
531 "traffic-queues": trafficQueues,
532 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000533 }
534
535 // On receiving the CreateTrafficQueues request, the driver should create corresponding
536 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000537 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530538 log.Fields{"direction": sq.direction,
539 "traffic-queues": trafficQueues,
540 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530541 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000542 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
543 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000544 TrafficQueues: trafficQueues,
545 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530546 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000547 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000548 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530549 "direction": sq.direction,
550 "traffic-queues": trafficQueues,
551 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000552
Esin Karamanccb714b2019-11-29 15:02:06 +0000553 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700554 multicastTrafficQueues := f.techprofile.GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance))
Esin Karamanccb714b2019-11-29 15:02:06 +0000555 if len(multicastTrafficQueues) > 0 {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700556 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 +0000557 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
558 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000559 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000560 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700561 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000562 gemPortID: multicastQueuePerPonPort.GemportId,
563 servicePriority: multicastQueuePerPonPort.Priority,
564 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700565 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000566 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400567 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700568 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400569 return err
570 }
Shrey Baid26912972020-04-16 21:02:31 +0530571
Neha Sharma96b7bf22020-06-15 10:37:32 +0000572 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000573 }
574 }
575 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000576 return nil
577}
578
salmansiddiqui7ac62132019-08-22 03:58:50 +0000579// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530580func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400581
582 var Direction string
583 var SchedCfg *tp_pb.SchedulerConfig
584 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000585 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530586 log.Fields{
587 "direction": sq.direction,
588 "intf-id": sq.intfID,
589 "onu-id": sq.onuID,
590 "uni-id": sq.uniID,
591 "uni-port": sq.uniPort,
592 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000593 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700594 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400595 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000596 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700597 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400598 Direction = "downstream"
599 }
600
Girish Gowdraa482f272021-03-24 23:04:19 -0700601 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 -0400602
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700603 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000604 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000605
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700606 TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000607 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530608 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
609 log.Fields{
610 "intf-id": sq.intfID,
611 "direction": sq.direction,
612 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000613 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400614
npujarec5762e2020-01-01 14:08:48 +0530615 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000616 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
617 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000618 TrafficQueues: TrafficQueues,
619 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000620 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530621 log.Fields{
622 "intf-id": sq.intfID,
623 "traffic-queues": TrafficQueues,
624 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400625 }
Gamze Abakacb0e6772021-06-10 08:32:12 +0000626 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id, "trafficQueues": TrafficQueues})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400627
Gamze Abakacb0e6772021-06-10 08:32:12 +0000628 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
629 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
630 IntfId: sq.intfID, OnuId: sq.onuID,
631 UniId: sq.uniID, PortNo: sq.uniPort,
632 TrafficScheds: TrafficSched}); err != nil {
633 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
634 log.Fields{
635 "intf-id": sq.intfID,
636 "traffic-schedulers": TrafficSched,
637 "onu-id": sq.onuID,
638 "uni-id": sq.uniID,
639 "uni-port": sq.uniPort}, err)
640 }
641
642 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
643 log.Fields{"device-id": f.deviceHandler.device.Id,
644 "intf-id": sq.intfID,
645 "onu-id": sq.onuID,
646 "uni-id": sq.uniID,
647 "uni-port": sq.uniPort})
648
649 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700650 allocID := sq.tpInst.(*tp_pb.TechProfileInstance).UsScheduler.AllocId
Gamze Abakacb0e6772021-06-10 08:32:12 +0000651 f.resourceMgr.FreeAllocID(ctx, sq.intfID, sq.onuID, sq.uniID, allocID)
652 // Delete the TCONT on the ONU.
653 uni := getUniPortPath(f.deviceHandler.device.Id, sq.intfID, int32(sq.onuID), int32(sq.uniID))
654 tpPath := f.getTPpath(ctx, sq.intfID, uni, sq.tpID)
655 if err := f.sendDeleteTcontToChild(ctx, sq.intfID, sq.onuID, sq.uniID, allocID, tpPath); err != nil {
656 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
657 log.Fields{
658 "intf": sq.intfID,
659 "onu-id": sq.onuID,
660 "uni-id": sq.uniID,
661 "device-id": f.deviceHandler.device.Id,
662 "alloc-id": allocID})
663 }
664 }
665 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000666
667 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400668 * delete the meter id on the KV store.
669 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700670 err = f.resourceMgr.RemoveMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400671 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530672 return olterrors.NewErrAdapter("unable-to-remove-meter",
673 log.Fields{
674 "onu": sq.onuID,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700675 "device-id": f.deviceHandler.device.Id,
676 "intf-id": sq.intfID,
677 "onu-id": sq.onuID,
678 "uni-id": sq.uniID,
679 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400680 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000681 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530682 log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530683 "dir": Direction,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700684 "device-id": f.deviceHandler.device.Id,
685 "intf-id": sq.intfID,
686 "onu-id": sq.onuID,
687 "uni-id": sq.uniID,
688 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400689 return err
690}
691
Gamze Abakafee36392019-10-03 11:17:24 +0000692// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700693func (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 +0000694 var allocIDs []uint32
695 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530696 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530697 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000698 var err error
npujarec5762e2020-01-01 14:08:48 +0530699 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
700 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000701 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530702
Neha Sharma96b7bf22020-06-15 10:37:32 +0000703 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530704 "intf-id": intfID,
705 "onu-id": onuID,
706 "uni-id": uniID,
707 "device-id": f.deviceHandler.device.Id,
708 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530709
Manikkaraj kb1d51442019-07-23 10:41:02 -0400710 // Check tech profile instance already exists for derived port name
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700711 techProfileInstance, _ := f.techprofile.GetTPInstance(ctx, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000712 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000713 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530714 log.Fields{
715 "path": tpPath,
716 "device-id": f.deviceHandler.device.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700717 techProfileInstance, err = f.techprofile.CreateTechProfileInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000718 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530719 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000720 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530721 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700722 "err": err,
Shrey Baid26912972020-04-16 21:02:31 +0530723 "tp-id": TpID,
724 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000725 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530726 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400727 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700728 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400729 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530730 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000731 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530732 log.Fields{
733 "uni": uni,
734 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530735 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530736 }
Gamze Abakafee36392019-10-03 11:17:24 +0000737
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700738 switch tpInst := techProfileInstance.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700739 case *tp_pb.TechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700740 if UsMeterID != 0 {
741 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
742 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
743 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000744 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700745 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700746 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700747 "onu-id": onuID,
748 "uni-id": uniID,
749 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700750 "meter-id": UsMeterID,
751 "device-id": f.deviceHandler.device.Id})
752 return 0, nil, nil
753 }
754 }
755 if DsMeterID != 0 {
756 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
757 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
758 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000759 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700760 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700761 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700762 "onu-id": onuID,
763 "uni-id": uniID,
764 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700765 "meter-id": DsMeterID,
766 "device-id": f.deviceHandler.device.Id})
767 return 0, nil, nil
768 }
769 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700770 allocID := tpInst.UsScheduler.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700771 for _, gem := range tpInst.UpstreamGemPortAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700772 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700773 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700774 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000775
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700776 if tpInstanceExists {
777 return allocID, gemPortIDs, techProfileInstance
778 }
779
780 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700781 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700782 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000783 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700784 log.Fields{
Matteo Scandolo84585372021-03-18 14:21:22 -0700785 "intf-id": intfID,
786 "onu-id": onuID,
787 "uni-id": uniID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700788 "alloc-ids": allocIDs,
789 "gemports": allgemPortIDs,
790 "device-id": f.deviceHandler.device.Id})
791 // Send Tconts and GEM ports to KV store
792 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530793 return allocID, gemPortIDs, techProfileInstance
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700794 case *openoltpb2.EponTechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700795 // CreateSchedulerQueues for EPON needs to be implemented here
796 // when voltha-protos for EPON is completed.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700797 allocID := tpInst.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700798 for _, gem := range tpInst.UpstreamQueueAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700799 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700800 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700801 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700802
803 if tpInstanceExists {
804 return allocID, gemPortIDs, techProfileInstance
805 }
806
807 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700808 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700809 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000810 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700811 log.Fields{
812 "alloc-ids": allocIDs,
813 "gemports": allgemPortIDs,
814 "device-id": f.deviceHandler.device.Id})
815 // Send Tconts and GEM ports to KV store
816 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
817 return allocID, gemPortIDs, techProfileInstance
818 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000819 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700820 log.Fields{
821 "tpInst": tpInst})
822 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530823 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530824}
825
npujarec5762e2020-01-01 14:08:48 +0530826func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530827
Neha Sharma96b7bf22020-06-15 10:37:32 +0000828 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530829 log.Fields{
830 "intf-id": intfID,
831 "onu-id": onuID,
832 "uni-id": uniID,
833 "alloc-id": allocID,
834 "gemport-ids": gemPortIDs,
835 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530836 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530837 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000838 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 +0530839 }
npujarec5762e2020-01-01 14:08:48 +0530840 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000841 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 +0530842 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700843
Neha Sharma96b7bf22020-06-15 10:37:32 +0000844 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 -0400845 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530846 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400847 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530848}
849
Neha Sharma96b7bf22020-06-15 10:37:32 +0000850func (f *OpenOltFlowMgr) populateTechProfilePerPonPort(ctx context.Context) error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000851 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530852 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000853 for _, intfID := range techRange.IntfIds {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700854 f.techprofile = f.resourceMgr.PonRsrMgr.TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400855 tpCount++
Neha Sharma96b7bf22020-06-15 10:37:32 +0000856 logger.Debugw(ctx, "init-tech-profile-done",
Shrey Baid26912972020-04-16 21:02:31 +0530857 log.Fields{
858 "intf-id": intfID,
859 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530860 }
861 }
862 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400863 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530864 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530865 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800866 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530867 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
868 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530869 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000870 logger.Infow(ctx, "populated-techprofile-for-ponports-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530871 log.Fields{
872 "numofTech": tpCount,
873 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
874 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530875 return nil
876}
877
Gamze Abaka7650be62021-02-26 10:50:36 +0000878func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
879 flowContext.classifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000880 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530881 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000882 "uplinkClassifier": flowContext.classifier,
883 "uplinkAction": flowContext.action})
884 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
Manikkaraj k884c1242019-04-11 16:26:42 +0530885 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530886}
887
Gamze Abaka7650be62021-02-26 10:50:36 +0000888func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
889 downlinkClassifier := flowContext.classifier
890 downlinkAction := flowContext.action
891
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700892 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000893 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530894 log.Fields{
895 "downlinkClassifier": downlinkClassifier,
896 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400897 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
898 if vlan, exists := downlinkClassifier[VlanVid]; exists {
899 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700900 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Gamze Abaka7650be62021-02-26 10:50:36 +0000901 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, flowContext.intfID, flowContext.onuID, flowContext.uniID) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000902 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530903 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000904 "flow": flowContext.logicalFlow,
Shrey Baid26912972020-04-16 21:02:31 +0530905 "device-id": f.deviceHandler.device.Id,
Gamze Abaka7650be62021-02-26 10:50:36 +0000906 "onu-id": flowContext.onuID,
907 "intf-id": flowContext.intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800908 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400909 }
910 }
911 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530912 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400913
Manikkaraj k884c1242019-04-11 16:26:42 +0530914 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700915 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400916 // vlan_vid is a uint32. must be type asserted as such or conversion fails
917 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530918 if ok {
919 downlinkAction[VlanVid] = dlClVid & 0xfff
920 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530921 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530922 "reason": "failed-to-convert-vlanid-classifier",
923 "vlan-id": VlanVid,
924 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530925 }
926
Gamze Abaka7650be62021-02-26 10:50:36 +0000927 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +0530928}
929
Gamze Abaka7650be62021-02-26 10:50:36 +0000930func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700931
Gamze Abaka7650be62021-02-26 10:50:36 +0000932 intfID := flowContext.intfID
933 onuID := flowContext.onuID
934 uniID := flowContext.uniID
935 classifier := flowContext.classifier
936 action := flowContext.action
937 allocID := flowContext.allocID
938 gemPortID := flowContext.gemPortID
939 tpID := flowContext.tpID
940 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +0000941 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530942 log.Fields{
943 "intf-id": intfID,
944 "onu-id": onuID,
945 "uni-id": uniID,
946 "device-id": f.deviceHandler.device.Id,
947 "classifier": classifier,
948 "action": action,
949 "direction": direction,
950 "alloc-id": allocID,
951 "gemport-id": gemPortID,
952 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700953
954 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000955 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +0530956 log.Fields{
957 "device-id": f.deviceHandler.device.Id,
958 "intf-id": intfID,
959 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800960 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530961 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800962 classifierProto, err := makeOpenOltClassifierField(classifier)
963 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530964 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530965 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000966 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +0530967 log.Fields{
968 "classifier": *classifierProto,
969 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +0000970 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800971 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530972 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530973 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000974 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +0530975 log.Fields{
976 "action": *actionProto,
977 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +0000978 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530979 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530980 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800981 log.Fields{
982 "classifier": classifier,
983 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +0530984 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800985 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530986 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700987
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700988 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700989 OnuId: int32(onuID),
990 UniId: int32(uniID),
991 FlowId: logicalFlow.Id,
992 FlowType: direction,
993 AllocId: int32(allocID),
994 NetworkIntfId: int32(networkIntfID),
995 GemportId: int32(gemPortID),
996 Classifier: classifierProto,
997 Action: actionProto,
998 Priority: int32(logicalFlow.Priority),
999 Cookie: logicalFlow.Cookie,
1000 PortNo: flowContext.portNo,
1001 TechProfileId: tpID,
1002 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1003 PbitToGemport: flowContext.pbitToGem,
1004 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001005 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001006 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001007 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301008 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001009 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301010 log.Fields{"direction": direction,
1011 "device-id": f.deviceHandler.device.Id,
1012 "flow": flow,
1013 "intf-id": intfID,
1014 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001015
David K. Bainbridge794735f2020-02-11 21:01:37 -08001016 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301017}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001018
Gamze Abaka7650be62021-02-26 10:50:36 +00001019func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1020
1021 intfID := flowContext.intfID
1022 onuID := flowContext.onuID
1023 uniID := flowContext.uniID
1024 logicalFlow := flowContext.logicalFlow
1025 classifier := flowContext.classifier
1026 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301027
Neha Sharma96b7bf22020-06-15 10:37:32 +00001028 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301029 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301030 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001031 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301032 "action": action,
1033 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001034 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301035 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301036
1037 // Clear the action map
1038 for k := range action {
1039 delete(action, k)
1040 }
1041
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001042 action[TrapToHost] = true
1043 classifier[UDPSrc] = uint32(68)
1044 classifier[UDPDst] = uint32(67)
1045 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301046
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001047 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001048 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301049 log.Fields{
1050 "device-id": f.deviceHandler.device.Id,
1051 "intf-id": intfID,
1052 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001053 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301054 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301055
Neha Sharma96b7bf22020-06-15 10:37:32 +00001056 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301057 log.Fields{
1058 "ul_classifier": classifier,
1059 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001060 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301061 "intf-id": intfID,
1062 "onu-id": onuID,
1063 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301064
David K. Bainbridge794735f2020-02-11 21:01:37 -08001065 classifierProto, err := makeOpenOltClassifierField(classifier)
1066 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301067 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301068 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001069 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001070 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001071 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301072 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301073 }
1074
David K. Bainbridge794735f2020-02-11 21:01:37 -08001075 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001076 OnuId: int32(onuID),
1077 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001078 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001079 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001080 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001081 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001082 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301083 Classifier: classifierProto,
1084 Action: actionProto,
1085 Priority: int32(logicalFlow.Priority),
1086 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001087 PortNo: flowContext.portNo,
1088 TechProfileId: flowContext.tpID,
1089 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1090 PbitToGemport: flowContext.pbitToGem,
1091 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001092 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001093 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001094 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001095 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001096 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301097 log.Fields{
1098 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001099 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301100 "intf-id": intfID,
1101 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301102
David K. Bainbridge794735f2020-02-11 21:01:37 -08001103 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301104}
1105
Esin Karamanae41e2b2019-12-17 18:13:13 +00001106//addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001107func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1108 delete(flowContext.classifier, VlanVid)
1109 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001110}
1111
1112//addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001113func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1114
1115 intfID := flowContext.intfID
1116 onuID := flowContext.onuID
1117 uniID := flowContext.uniID
1118 logicalFlow := flowContext.logicalFlow
1119 classifier := flowContext.classifier
1120 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001121
Neha Sharma96b7bf22020-06-15 10:37:32 +00001122 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001123 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301124 return olterrors.NewErrNotFound("nni-interface-id",
1125 log.Fields{
1126 "classifier": classifier,
1127 "action": action,
1128 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001129 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001130 }
1131
1132 // Clear the action map
1133 for k := range action {
1134 delete(action, k)
1135 }
1136
1137 action[TrapToHost] = true
1138 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001139
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001140 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001141 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001142 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001143 }
1144
Neha Sharma96b7bf22020-06-15 10:37:32 +00001145 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301146 log.Fields{
1147 "ul_classifier": classifier,
1148 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001149 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301150 "device-id": f.deviceHandler.device.Id,
1151 "intf-id": intfID,
1152 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001153
David K. Bainbridge794735f2020-02-11 21:01:37 -08001154 classifierProto, err := makeOpenOltClassifierField(classifier)
1155 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301156 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001157 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001158 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301159 log.Fields{
1160 "classifier": *classifierProto,
1161 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001162 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001163 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301164 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001165 }
1166
David K. Bainbridge794735f2020-02-11 21:01:37 -08001167 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001168 OnuId: int32(onuID),
1169 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001170 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001171 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001172 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001173 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001174 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001175 Classifier: classifierProto,
1176 Action: actionProto,
1177 Priority: int32(logicalFlow.Priority),
1178 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001179 PortNo: flowContext.portNo,
1180 TechProfileId: flowContext.tpID,
1181 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1182 PbitToGemport: flowContext.pbitToGem,
1183 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001184 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001185
David K. Bainbridge794735f2020-02-11 21:01:37 -08001186 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001187 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 -08001188 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001189
David K. Bainbridge794735f2020-02-11 21:01:37 -08001190 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001191}
1192
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001193// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001194func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1195 intfID := flowContext.intfID
1196 onuID := flowContext.onuID
1197 uniID := flowContext.uniID
1198 portNo := flowContext.portNo
1199 allocID := flowContext.allocID
1200 gemPortID := flowContext.gemPortID
1201 logicalFlow := flowContext.logicalFlow
1202 classifier := flowContext.classifier
1203 action := flowContext.action
1204
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001205 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301206 log.Fields{
1207 "intf-id": intfID,
1208 "onu-id": onuID,
1209 "port-no": portNo,
1210 "alloc-id": allocID,
1211 "gemport-id": gemPortID,
1212 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001213 "flow": logicalFlow,
1214 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301215
1216 uplinkClassifier := make(map[string]interface{})
1217 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301218
manikkaraj kbf256be2019-03-25 00:13:48 +05301219 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001220 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001221 uplinkClassifier[PacketTagType] = SingleTag
1222 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001223 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301224 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001225 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001226 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001227 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301228 "device-id": f.deviceHandler.device.Id,
1229 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001230 "intf-id": intfID,
1231 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001232 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301233 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001234 //Add Uplink EthType Flow
1235 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301236 log.Fields{
1237 "ul_classifier": uplinkClassifier,
1238 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001239 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301240 "device-id": f.deviceHandler.device.Id,
1241 "intf-id": intfID,
1242 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301243
David K. Bainbridge794735f2020-02-11 21:01:37 -08001244 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1245 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301246 return olterrors.NewErrInvalidValue(log.Fields{
1247 "classifier": uplinkClassifier,
1248 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301249 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001250 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301251 log.Fields{
1252 "classifier": *classifierProto,
1253 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001254 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001255 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301256 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301257 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001258 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301259 log.Fields{
1260 "action": *actionProto,
1261 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001262 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301263 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301264 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001265 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301266 "action": action,
1267 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001268 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301269 }
1270
David K. Bainbridge794735f2020-02-11 21:01:37 -08001271 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001272 OnuId: int32(onuID),
1273 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001274 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001275 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001276 AllocId: int32(allocID),
1277 NetworkIntfId: int32(networkIntfID),
1278 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301279 Classifier: classifierProto,
1280 Action: actionProto,
1281 Priority: int32(logicalFlow.Priority),
1282 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001283 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001284 TechProfileId: flowContext.tpID,
1285 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1286 PbitToGemport: flowContext.pbitToGem,
1287 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001288 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001289 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001290 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001291 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001292 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301293 log.Fields{
1294 "device-id": f.deviceHandler.device.Id,
1295 "onu-id": onuID,
1296 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001297 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301298 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001299
David K. Bainbridge794735f2020-02-11 21:01:37 -08001300 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301301}
1302
David K. Bainbridge794735f2020-02-11 21:01:37 -08001303func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001304 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001305
1306 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1307 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1308 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001309 if vlanID != ReservedVlan {
1310 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001311 classifier.OVid = vid
1312 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301313 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001314 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1315 vid := uint32(metadata)
1316 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001317 classifier.IVid = vid
1318 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301319 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301320 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001321 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301322 classifier.OPbits = vlanPcp
1323 } else {
1324 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301325 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001326 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1327 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1328 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1329 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001330 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001331 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1332 classifier.PktTagType = pktTagType
1333
1334 switch pktTagType {
1335 case SingleTag:
1336 case DoubleTag:
1337 case Untagged:
1338 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001339 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301340 }
1341 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001342 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301343}
1344
Gamze Abaka724d0852020-03-18 12:10:24 +00001345func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001346 var actionCmd openoltpb2.ActionCmd
1347 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301348 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001349 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301350 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001351 if _, ok := actionInfo[VlanPcp]; ok {
1352 action.Cmd.RemarkInnerPbits = true
1353 action.IPbits = actionInfo[VlanPcp].(uint32)
1354 if _, ok := actionInfo[VlanVid]; ok {
1355 action.Cmd.TranslateInnerTag = true
1356 action.IVid = actionInfo[VlanVid].(uint32)
1357 }
1358 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001359 } else if _, ok := actionInfo[PushVlan]; ok {
1360 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301361 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001362 if _, ok := actionInfo[VlanPcp]; ok {
1363 action.OPbits = actionInfo[VlanPcp].(uint32)
1364 action.Cmd.RemarkOuterPbits = true
1365 if _, ok := classifierInfo[VlanVid]; ok {
1366 action.IVid = classifierInfo[VlanVid].(uint32)
1367 action.Cmd.TranslateInnerTag = true
1368 }
1369 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001370 } else if _, ok := actionInfo[TrapToHost]; ok {
1371 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301372 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001373 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301374 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001375 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301376}
1377
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001378// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001379func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001380 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301381}
1382
Gamze Abakafee36392019-10-03 11:17:24 +00001383// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001384func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301385 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001386 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1387
Gamze Abakafee36392019-10-03 11:17:24 +00001388 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301389 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001390 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301391 // return err
1392 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001393 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001394 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 +00001395 }
1396 return nil
1397}
1398
1399// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301400func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001401 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001402 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001403 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001404 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301405 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1406 log.Fields{
1407 "tp-id": tpID,
1408 "uni-port-name": uniPortName,
1409 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001410 }
1411 return nil
1412}
1413
David K. Bainbridge794735f2020-02-11 21:01:37 -08001414func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001415
1416 var intfID uint32
1417 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1418 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1419 */
1420 if deviceFlow.AccessIntfId != -1 {
1421 intfID = uint32(deviceFlow.AccessIntfId)
1422 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001423 // We need to log the valid interface ID.
1424 // 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 +00001425 intfID = uint32(deviceFlow.NetworkIntfId)
1426 }
1427
Neha Sharma96b7bf22020-06-15 10:37:32 +00001428 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301429 "flow": *deviceFlow,
1430 "device-id": f.deviceHandler.device.Id,
1431 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001432 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001433
1434 st, _ := status.FromError(err)
1435 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001436 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001437 "err": err,
1438 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301439 "device-id": f.deviceHandler.device.Id,
1440 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001441 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301442 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001443
1444 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001445 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301446 log.Fields{"err": err,
1447 "device-flow": deviceFlow,
1448 "device-id": f.deviceHandler.device.Id,
1449 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001450 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001451 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001452 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301453 log.Fields{
1454 "flow": *deviceFlow,
1455 "device-id": f.deviceHandler.device.Id,
1456 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001457
1458 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1459 if deviceFlow.AccessIntfId != -1 {
1460 // No need to register the flow if it is a trap on nni flow.
1461 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1462 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1463 return err
1464 }
1465 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001466 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001467}
1468
Neha Sharma96b7bf22020-06-15 10:37:32 +00001469func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1470 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301471 log.Fields{
1472 "flow": *deviceFlow,
1473 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001474 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001475 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001476 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001477 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301478 log.Fields{
1479 "err": err,
1480 "deviceFlow": deviceFlow,
1481 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001482 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001483 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001484 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001485 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001486
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001487 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001488 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001489 "of-flow-id": ofFlowID,
1490 "flow": *deviceFlow,
1491 "device-id": f.deviceHandler.device.Id,
1492 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001493 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301494}
1495
David K. Bainbridge794735f2020-02-11 21:01:37 -08001496func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001497
1498 classifierInfo := make(map[string]interface{})
1499 actionInfo := make(map[string]interface{})
1500
1501 classifierInfo[EthType] = uint32(LldpEthType)
1502 classifierInfo[PacketTagType] = Untagged
1503 actionInfo[TrapToHost] = true
1504
1505 // LLDP flow is installed to trap LLDP packets on the NNI port.
1506 // We manage flow_id resource pool on per PON port basis.
1507 // Since this situation is tricky, as a hack, we pass the NNI port
1508 // index (network_intf_id) as PON port Index for the flow_id resource
1509 // pool. Also, there is no ONU Id available for trapping LLDP packets
1510 // on NNI port, use onu_id as -1 (invalid)
1511 // ****************** CAVEAT *******************
1512 // This logic works if the NNI Port Id falls within the same valid
1513 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1514 // we need to have a re-look at this.
1515 // *********************************************
1516
1517 var onuID = -1
1518 var uniID = -1
1519 var gemPortID = -1
1520
Neha Sharma96b7bf22020-06-15 10:37:32 +00001521 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001522 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301523 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001524 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001525 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001526 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001527 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001528 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001529
David K. Bainbridge794735f2020-02-11 21:01:37 -08001530 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1531 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301532 return olterrors.NewErrInvalidValue(
1533 log.Fields{
1534 "classifier": classifierInfo,
1535 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001536 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001537 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301538 log.Fields{
1539 "classifier": *classifierProto,
1540 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001541 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001542 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301543 return olterrors.NewErrInvalidValue(
1544 log.Fields{
1545 "action": actionInfo,
1546 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001547 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001548 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301549 log.Fields{
1550 "action": *actionProto,
1551 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001552
1553 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1554 OnuId: int32(onuID), // OnuId not required
1555 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001556 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001557 FlowType: Downstream,
1558 NetworkIntfId: int32(networkInterfaceID),
1559 GemportId: int32(gemPortID),
1560 Classifier: classifierProto,
1561 Action: actionProto,
1562 Priority: int32(flow.Priority),
1563 Cookie: flow.Cookie,
1564 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001565 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001566 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301567 log.Fields{
1568 "flow": downstreamflow,
1569 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001570 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001571 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301572 log.Fields{
1573 "device-id": f.deviceHandler.device.Id,
1574 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001575 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001576
David K. Bainbridge794735f2020-02-11 21:01:37 -08001577 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301578}
1579
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001580func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1581 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001582}
1583
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001584//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001585func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001586 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1587 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1588 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001589 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301590 log.Fields{
1591 "intf-id": intfID,
1592 "onu-id": onuID,
1593 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001594 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001595 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301596 return nil, olterrors.NewErrNotFound("onu-child-device",
1597 log.Fields{
1598 "onu-id": onuID,
1599 "intf-id": intfID,
1600 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001601 }
1602 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1603 //better to ad the device to cache here.
1604 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1605 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001606 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301607 log.Fields{
1608 "intf-id": intfID,
1609 "onu-id": onuID,
1610 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001611 }
1612
1613 return onuDev.(*OnuDevice), nil
1614}
1615
1616//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001617func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1618 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301619 log.Fields{
1620 "pon-port": intfID,
1621 "onu-id": onuID,
1622 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001623 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001624 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001625 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301626 return nil, olterrors.NewErrNotFound("onu",
1627 log.Fields{
1628 "interface-id": parentPortNo,
1629 "onu-id": onuID,
1630 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001631 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301632 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001633 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301634 log.Fields{
1635 "device-id": f.deviceHandler.device.Id,
1636 "child_device_id": onuDevice.Id,
1637 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301638 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301639}
1640
Neha Sharma96b7bf22020-06-15 10:37:32 +00001641func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1642 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301643 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001644 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301645 log.Fields{
1646 "intf-id": intfID,
1647 "onu-id": onuID,
1648 "uni-id": uniID,
1649 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001650 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301651 }
1652
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001653 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpInstancePath: tpPath, GemPortId: gemPortID}
1654 logger.Infow(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301655 log.Fields{
1656 "msg": *delGemPortMsg,
1657 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001658 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301659 delGemPortMsg,
1660 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001661 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001662 onuDev.deviceType,
1663 onuDev.deviceID,
1664 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301665 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1666 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001667 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301668 "to-adapter": onuDev.deviceType,
1669 "onu-id": onuDev.deviceID,
1670 "proxyDeviceID": onuDev.proxyDeviceID,
1671 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301672 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001673 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301674 log.Fields{
1675 "msg": delGemPortMsg,
1676 "from-adapter": f.deviceHandler.device.Type,
1677 "to-adapter": onuDev.deviceType,
1678 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301679 return nil
1680}
1681
Neha Sharma96b7bf22020-06-15 10:37:32 +00001682func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1683 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301684 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001685 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301686 log.Fields{
1687 "intf-id": intfID,
1688 "onu-id": onuID,
1689 "uni-id": uniID,
1690 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001691 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301692 }
1693
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001694 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpInstancePath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001695 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301696 log.Fields{
1697 "msg": *delTcontMsg,
1698 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001699 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301700 delTcontMsg,
1701 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001702 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001703 onuDev.deviceType,
1704 onuDev.deviceID,
1705 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301706 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1707 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001708 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301709 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1710 "proxyDeviceID": onuDev.proxyDeviceID,
1711 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301712 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001713 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301714 log.Fields{
1715 "msg": delTcontMsg,
1716 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301717 return nil
1718}
1719
Girish Gowdrac3037402020-01-22 20:29:53 +05301720// Once the gemport is released for a given onu, it also has to be cleared from local cache
1721// which was used for deriving the gemport->logicalPortNo during packet-in.
1722// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1723// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001724func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001725 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301726 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001727 "gem-port-id": gemPortID,
1728 "intf-id": intfID,
1729 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001730 "device-id": f.deviceHandler.device.Id})
1731 f.onuGemInfoLock.RLock()
1732 onugem, ok := f.onuGemInfoMap[onuID]
1733 f.onuGemInfoLock.RUnlock()
1734 if !ok {
1735 logger.Warnw(ctx, "onu gem info already cleared from cache", log.Fields{
1736 "gem-port-id": gemPortID,
1737 "intf-id": intfID,
1738 "onu-id": onuID,
1739 "device-id": f.deviceHandler.device.Id})
1740 return
1741 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001742deleteLoop:
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001743 for j, gem := range onugem.GemPorts {
1744 // If the gemport is found, delete it from local cache.
1745 if gem == gemPortID {
1746 onugem.GemPorts = append(onugem.GemPorts[:j], onugem.GemPorts[j+1:]...)
1747 f.onuGemInfoLock.Lock()
1748 f.onuGemInfoMap[onuID] = onugem
1749 f.onuGemInfoLock.Unlock()
1750 logger.Infow(ctx, "removed-gemport-from-local-cache",
1751 log.Fields{
1752 "intf-id": intfID,
1753 "onu-id": onuID,
1754 "deletedgemport-id": gemPortID,
1755 "gemports": onugem.GemPorts,
1756 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001757 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301758 }
1759 }
1760}
1761
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301762//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001763// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001764func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Girish Gowdra82c80982021-03-26 16:22:02 -07001765 gemPortID int32, flowID uint64, portNum uint32, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001766
Girish Gowdraa482f272021-03-24 23:04:19 -07001767 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
1768 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001769 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1770 log.Fields{
1771 "tpPath": tpPath,
1772 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001773
1774 used := f.isGemPortUsedByAnotherFlow(uint32(gemPortID))
1775
1776 if used {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001777 f.gemToFlowIDsKey.RLock()
1778 flowIDs := f.gemToFlowIDs[uint32(gemPortID)]
1779 f.gemToFlowIDsKey.RUnlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001780
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001781 for i, flowIDinMap := range flowIDs {
1782 if flowIDinMap == flowID {
1783 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001784 f.gemToFlowIDsKey.Lock()
1785 f.gemToFlowIDs[uint32(gemPortID)] = flowIDs
1786 f.gemToFlowIDsKey.Unlock()
1787 // everytime gemToFlowIDs cache is updated the same should be updated
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001788 // in kv store by calling UpdateFlowIDsForGem
Girish Gowdraa482f272021-03-24 23:04:19 -07001789 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, intfID, uint32(gemPortID), flowIDs); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001790 return err
1791 }
1792 break
1793 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001794 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001795 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1796 log.Fields{
1797 "gemport-id": gemPortID,
1798 "usedByFlows": flowIDs,
1799 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -07001800
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001801 return nil
1802 }
1803 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 -07001804 f.deleteGemPortFromLocalCache(ctx, intfID, uint32(onuID), uint32(gemPortID))
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001805 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, intfID, uint32(onuID), uint32(gemPortID)) // ignore error and proceed.
1806 //everytime an entry is deleted from gemToFlowIDs cache, the same should be updated in kv as well
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001807 // by calling DeleteFlowIDsForGem
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001808 f.gemToFlowIDsKey.Lock()
1809 delete(f.gemToFlowIDs, uint32(gemPortID))
1810 f.gemToFlowIDsKey.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001811
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001812 f.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, uint32(gemPortID))
1813
1814 f.resourceMgr.FreeGemPortID(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001815
1816 // Delete the gem port on the ONU.
Girish Gowdraa482f272021-03-24 23:04:19 -07001817 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001818 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
1819 log.Fields{
1820 "err": err,
Girish Gowdraa482f272021-03-24 23:04:19 -07001821 "intfID": intfID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001822 "onu-id": onuID,
1823 "uni-id": uniID,
1824 "device-id": f.deviceHandler.device.Id,
1825 "gemport-id": gemPortID})
1826 }
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
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301875 return nil
1876}
1877
David K. Bainbridge794735f2020-02-11 21:01:37 -08001878// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07001879func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001880 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05301881 log.Fields{
1882 "flowDirection": flowDirection,
1883 "flow": *flow,
1884 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001885
1886 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001887 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00001888 }
1889
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301890 classifierInfo := make(map[string]interface{})
1891
Neha Sharma96b7bf22020-06-15 10:37:32 +00001892 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301893 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001894 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001895 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301896 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301897
David K. Bainbridge794735f2020-02-11 21:01:37 -08001898 onuID := int32(onu)
1899 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001900 tpID, err := getTpIDFromFlow(ctx, flow)
1901 if err != nil {
1902 return olterrors.NewErrNotFound("tp-id",
1903 log.Fields{
1904 "flow": flow,
1905 "intf-id": Intf,
1906 "onu-id": onuID,
1907 "uni-id": uniID,
1908 "device-id": f.deviceHandler.device.Id}, err)
1909 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301910
1911 for _, field := range flows.GetOfbFields(flow) {
1912 if field.Type == flows.IP_PROTO {
1913 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00001914 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301915 }
1916 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001917 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05301918 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001919 "flow-id": flow.Id,
1920 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05301921 "onu-id": onuID,
1922 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301923
1924 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1925 onuID = -1
1926 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00001927 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
1928 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001929 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001930 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001931 log.Fields{
1932 "port-number": inPort,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001933 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001934 return err
David K. Bainbridge794735f2020-02-11 21:01:37 -08001935 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301936 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001937
1938 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
1939 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001940 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
1941 return err
1942 }
Girish Gowdra82c80982021-03-26 16:22:02 -07001943
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001944 f.flowIDToGemsLock.Lock()
1945 gems, ok := f.flowIDToGems[flow.Id]
1946 if !ok {
1947 logger.Errorw(ctx, "flow-id-to-gem-map-not-found", log.Fields{"flowID": flow.Id})
1948 f.flowIDToGemsLock.Unlock()
1949 return olterrors.NewErrNotFound("flow-id-to-gem-map-not-found", log.Fields{"flowID": flow.Id}, nil)
1950 }
1951 copyOfGems := make([]uint32, len(gems))
1952 _ = copy(copyOfGems, gems)
1953 // Delete the flow-id to gemport list entry from the map now the flow is deleted.
1954 delete(f.flowIDToGems, flow.Id)
1955 f.flowIDToGemsLock.Unlock()
1956
1957 logger.Debugw(ctx, "gems-to-be-cleared", log.Fields{"gems": copyOfGems})
1958 for _, gem := range copyOfGems {
1959 if err = f.clearResources(ctx, Intf, onuID, uniID, int32(gem), flow.Id, portNum, tpID); err != nil {
Girish Gowdra0aca4982021-01-04 12:44:27 -08001960 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001961 "flow-id": flow.Id,
1962 "device-id": f.deviceHandler.device.Id,
1963 "onu-id": onuID,
1964 "intf": Intf,
1965 "gem": gem,
1966 "err": err,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001967 })
1968 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301969 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301970 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001971
Girish Gowdra82c80982021-03-26 16:22:02 -07001972 // Decrement reference count for the meter associated with the given <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
1973 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, Intf, uint32(onuID), uint32(uniID), tpID, false); err != nil {
1974 return err
1975 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001976 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001977}
1978
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001979//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07001980func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001981
Matteo Scandolof16389e2021-05-18 00:47:08 +00001982 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301983 var direction string
1984 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001985
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301986 for _, action := range flows.GetActions(flow) {
1987 if action.Type == flows.OUTPUT {
1988 if out := action.GetOutput(); out != nil {
1989 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00001990 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301991 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001992 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07001993 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001994 }
1995 }
1996 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001997
1998 if flows.HasGroup(flow) {
1999 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002000 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Esin Karamanccb714b2019-11-29 15:02:06 +00002001 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302002 direction = Upstream
2003 } else {
2004 direction = Downstream
2005 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302006
Girish Gowdracefae192020-03-19 18:14:10 -07002007 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002008 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002009
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002010 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002011}
2012
Esin Karamanae41e2b2019-12-17 18:13:13 +00002013//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2014func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2015 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2016 if ethType, ok := classifierInfo[EthType]; ok {
2017 if ethType.(uint32) == IPv4EthType {
2018 if ipProto, ok := classifierInfo[IPProto]; ok {
2019 if ipProto.(uint32) == IgmpProto {
2020 return true
2021 }
2022 }
2023 }
2024 }
2025 }
2026 return false
2027}
2028
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002029// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
2030func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *voltha.OfpFlowStats, addFlow bool, flowMetadata *voltha.FlowMetadata) error {
2031 // Step1 : Fill flowControlBlock
2032 // Step2 : Push the flowControlBlock to ONU channel
2033 // Step3 : Wait on response channel for response
2034 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002035 startTime := time.Now()
2036 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002037 errChan := make(chan error)
2038 flowCb := flowControlBlock{
2039 ctx: ctx,
2040 addFlow: addFlow,
2041 flow: flow,
2042 flowMetadata: flowMetadata,
2043 errChan: &errChan,
2044 }
2045 inPort, outPort := getPorts(flow)
2046 var onuID uint32
2047 if inPort != InvalidPort && outPort != InvalidPort {
2048 _, _, onuID, _ = ExtractAccessFromFlow(inPort, outPort)
2049 }
2050 // inPort or outPort is InvalidPort for trap-from-nni flows.
2051 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2052 // Send the flowCb on the ONU flow channel
2053 f.incomingFlows[onuID] <- flowCb
2054 // Wait on the channel for flow handlers return value
2055 err := <-errChan
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002056 logger.Infow(ctx, "process-flow--received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002057 return err
2058}
2059
2060// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2061// Each incoming flow is processed in a synchronous manner, i.e., the flow is processed to completion before picking another
2062func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(subscriberFlowChannel chan flowControlBlock) {
2063 for {
2064 // block on the channel to receive an incoming flow
2065 // process the flow completely before proceeding to handle the next flow
2066 flowCb := <-subscriberFlowChannel
2067 if flowCb.addFlow {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002068 logger.Info(flowCb.ctx, "adding-flow-start")
2069 startTime := time.Now()
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002070 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002071 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002072 // Pass the return value over the return channel
2073 *flowCb.errChan <- err
2074 } else {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002075 logger.Info(flowCb.ctx, "removing-flow-start")
2076 startTime := time.Now()
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002077 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002078 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002079 // Pass the return value over the return channel
2080 *flowCb.errChan <- err
2081 }
2082 }
2083}
2084
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002085// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302086// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002087func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002088 classifierInfo := make(map[string]interface{})
2089 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002090 var UsMeterID uint32
2091 var DsMeterID uint32
2092
Neha Sharma96b7bf22020-06-15 10:37:32 +00002093 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302094 log.Fields{
2095 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002096 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002097 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002098
Neha Sharma96b7bf22020-06-15 10:37:32 +00002099 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002100 if err != nil {
2101 // Error logging is already done in the called function
2102 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002103 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302104 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002105
Esin Karamanccb714b2019-11-29 15:02:06 +00002106 if flows.HasGroup(flow) {
2107 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002108 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002109 }
2110
manikkaraj k17652a72019-05-06 09:06:36 -04002111 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002112 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002113 if err != nil {
2114 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002115 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002116 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002117
Neha Sharma96b7bf22020-06-15 10:37:32 +00002118 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302119 log.Fields{
2120 "classifierinfo_inport": classifierInfo[InPort],
2121 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002122 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002123
Humera Kouser94d7a842019-08-25 19:04:32 -04002124 if ethType, ok := classifierInfo[EthType]; ok {
2125 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002126 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002127 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002128 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002129 if ethType.(uint32) == PPPoEDEthType {
2130 if voltha.Port_ETHERNET_NNI == IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
2131 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2132 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2133 }
2134 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002135 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002136 if ipProto, ok := classifierInfo[IPProto]; ok {
2137 if ipProto.(uint32) == IPProtoDhcp {
2138 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302139 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002140 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002141 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002142 }
2143 }
2144 }
2145 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002146 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002147 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002148 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002149 }
A R Karthick1f85b802019-10-11 05:06:05 +00002150
npujarec5762e2020-01-01 14:08:48 +05302151 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002152 // also update flowmgr cache
2153 f.onuGemInfoLock.Lock()
2154 onugem, ok := f.onuGemInfoMap[onuID]
2155 if ok {
2156 found := false
2157 for _, uni := range onugem.UniPorts {
2158 if uni == portNo {
2159 found = true
2160 break
2161 }
2162 }
2163 if !found {
2164 onugem.UniPorts = append(onugem.UniPorts, portNo)
2165 f.onuGemInfoMap[onuID] = onugem
2166 logger.Infow(ctx, "added uni port to onugem cache", log.Fields{"uni": portNo})
2167 }
2168 }
2169 f.onuGemInfoLock.Unlock()
A R Karthick1f85b802019-10-11 05:06:05 +00002170
Neha Sharma96b7bf22020-06-15 10:37:32 +00002171 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002172 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302173 return olterrors.NewErrNotFound("tpid-for-flow",
2174 log.Fields{
2175 "flow": flow,
2176 "intf-id": IntfID,
2177 "onu-id": onuID,
2178 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002179 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002180 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302181 log.Fields{
2182 "tp-id": TpID,
2183 "intf-id": intfID,
2184 "onu-id": onuID,
2185 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002186 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002187 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002188 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002189 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002190 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002191 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002192
2193 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002194 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002195}
Girish Gowdra3d633032019-12-10 16:37:05 +05302196
Esin Karamanccb714b2019-11-29 15:02:06 +00002197// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002198func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002199 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002200 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302201 "classifier-info": classifierInfo,
2202 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002203
Esin Karaman65409d82020-03-18 10:58:18 +00002204 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002205 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002206 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002207 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002208
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002209 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002210
David K. Bainbridge794735f2020-02-11 21:01:37 -08002211 onuID := NoneOnuID
2212 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002213
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002214 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002215 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002216 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002217 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002218 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2219 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002220 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002221 }
2222 groupID := actionInfo[GroupID].(uint32)
2223 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002224 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002225 FlowType: Multicast,
2226 NetworkIntfId: int32(networkInterfaceID),
2227 GroupId: groupID,
2228 Classifier: classifierProto,
2229 Priority: int32(flow.Priority),
2230 Cookie: flow.Cookie}
2231
Kent Hagermane6ff1012020-07-14 15:07:53 -04002232 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002233 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002234 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002235 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002236 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002237 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002238 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002239 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002240 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002241 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002242 //cached group can be removed now
2243 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002244 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002245 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002246 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002247
David K. Bainbridge794735f2020-02-11 21:01:37 -08002248 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002249}
2250
Esin Karaman65409d82020-03-18 10:58:18 +00002251//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2252func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2253 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002254 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002255 if err != nil {
2256 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2257 }
2258 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002259 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002260
2261 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2262 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002263}
2264
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002265//sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002266func (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 -07002267
Neha Sharma96b7bf22020-06-15 10:37:32 +00002268 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302269 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002270 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302271 log.Fields{
2272 "intf-id": intfID,
2273 "onu-id": onuID,
2274 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002275 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302276 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002277 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002278
Neha Sharma96b7bf22020-06-15 10:37:32 +00002279 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002280 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{
2281 UniId: uniID,
2282 TpInstancePath: tpPath,
2283 TechTpInstance: &ic.InterAdapterTechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
2284 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002285 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002286 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
manikkaraj k17652a72019-05-06 09:06:36 -04002287 tpDownloadMsg,
2288 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03002289 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002290 onuDev.deviceType,
2291 onuDev.deviceID,
2292 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002293 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302294 return olterrors.NewErrCommunication("send-techprofile-download-request",
2295 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03002296 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05302297 "to-adapter": onuDev.deviceType,
2298 "onu-id": onuDev.deviceID,
2299 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002300 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002301 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302302 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302303}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002304
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302305//UpdateOnuInfo function adds onu info to cache and kvstore
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002306//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002307func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302308
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002309 f.onuGemInfoLock.RLock()
2310 _, ok := f.onuGemInfoMap[onuID]
2311 f.onuGemInfoLock.RUnlock()
Girish Gowdra9602eb42020-09-09 15:50:39 -07002312 // If the ONU already exists in onuGemInfo list, nothing to do
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002313 if ok {
2314 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2315 log.Fields{"onuID": onuID,
2316 "serialNum": serialNum})
2317 return nil
Girish Gowdra9602eb42020-09-09 15:50:39 -07002318 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002319
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002320 onuGemInfo := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2321 f.onuGemInfoLock.Lock()
2322 f.onuGemInfoMap[onuID] = &onuGemInfo
2323 f.onuGemInfoLock.Unlock()
2324 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onuID, onuGemInfo); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002325 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302326 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002327 logger.Infow(ctx, "updated-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302328 log.Fields{
2329 "intf-id": intfID,
2330 "onu-id": onuID,
2331 "serial-num": serialNum,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002332 "onu": onuGemInfo,
Shrey Baid26912972020-04-16 21:02:31 +05302333 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002334 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002335}
2336
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302337//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302338func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002339
Neha Sharma96b7bf22020-06-15 10:37:32 +00002340 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302341 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002342 "gem-port-id": gemPort,
2343 "intf-id": intfID,
2344 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002345 "device-id": f.deviceHandler.device.Id})
2346 f.onuGemInfoLock.RLock()
2347 onugem, ok := f.onuGemInfoMap[onuID]
2348 f.onuGemInfoLock.RUnlock()
2349 if !ok {
2350 logger.Warnw(ctx, "onu gem info is missing", log.Fields{
2351 "gem-port-id": gemPort,
2352 "intf-id": intfID,
2353 "onu-id": onuID,
2354 "device-id": f.deviceHandler.device.Id})
2355 return
2356 }
2357
2358 if onugem.OnuID == onuID {
2359 // check if gem already exists , else update the cache and kvstore
2360 for _, gem := range onugem.GemPorts {
2361 if gem == gemPort {
2362 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
2363 log.Fields{
2364 "gem": gemPort,
2365 "device-id": f.deviceHandler.device.Id})
2366 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302367 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302368 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002369 onugem.GemPorts = append(onugem.GemPorts, gemPort)
2370 f.onuGemInfoLock.Lock()
2371 f.onuGemInfoMap[onuID] = onugem
2372 f.onuGemInfoLock.Unlock()
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002373 logger.Debugw(ctx, "updated onu gem info from cache", log.Fields{"onugem": onugem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002374 } else {
2375 logger.Warnw(ctx, "mismatched onu id", log.Fields{
2376 "gem-port-id": gemPort,
2377 "intf-id": intfID,
2378 "onu-id": onuID,
2379 "device-id": f.deviceHandler.device.Id})
2380 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302381 }
npujarec5762e2020-01-01 14:08:48 +05302382 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302383 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002384 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302385 log.Fields{
2386 "intf-id": intfID,
2387 "onu-id": onuID,
2388 "gemPort": gemPort,
2389 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002390 return
2391 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002392 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302393 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002394 "gem-port-id": gemPort,
2395 "intf-id": intfID,
2396 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002397 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002398}
2399
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002400//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302401func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002402 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002403
2404 if packetIn.IntfType == "pon" {
2405 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002406 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002407 onuID, uniID := packetIn.OnuId, packetIn.UniId
2408 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 +00002409
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002410 if packetIn.PortNo != 0 {
2411 logicalPortNum = packetIn.PortNo
2412 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002413 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002414 }
2415 // 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 +00002416 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002417 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002418 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002419 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002420
2421 if logger.V(log.DebugLevel) {
2422 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2423 log.Fields{
2424 "logical-port-num": logicalPortNum,
2425 "intf-type": packetIn.IntfType,
2426 "packet": hex.EncodeToString(packetIn.Pkt),
2427 })
2428 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002429 return logicalPortNum, nil
2430}
2431
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002432//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002433func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002434 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002435
2436 ctag, priority, err := getCTagFromPacket(ctx, packet)
2437 if err != nil {
2438 return 0, err
2439 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302440
Esin Karaman7fb80c22020-07-16 14:23:33 +00002441 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002442 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002443 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002444 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002445 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302446 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002447 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302448 log.Fields{
2449 "pktinkey": pktInkey,
2450 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002451
2452 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002453 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302454 //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 +00002455 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302456 if err == nil {
2457 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002458 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302459 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002460 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002461 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302462 log.Fields{
2463 "pktinkey": pktInkey,
2464 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302465 return gemPortID, nil
2466 }
2467 }
Shrey Baid26912972020-04-16 21:02:31 +05302468 return uint32(0), olterrors.NewErrNotFound("gem-port",
2469 log.Fields{
2470 "pktinkey": pktInkey,
2471 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002472
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002473}
2474
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002475func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2476 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002477 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002478 classifier[PacketTagType] = DoubleTag
2479 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002480 /* We manage flowId resource pool on per PON port basis.
2481 Since this situation is tricky, as a hack, we pass the NNI port
2482 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002483 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002484 on NNI port, use onu_id as -1 (invalid)
2485 ****************** CAVEAT *******************
2486 This logic works if the NNI Port Id falls within the same valid
2487 range of PON Port Ids. If this doesn't work for some OLT Vendor
2488 we need to have a re-look at this.
2489 *********************************************
2490 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002491 onuID := -1
2492 uniID := -1
2493 gemPortID := -1
2494 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002495 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302496 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302497 return olterrors.NewErrNotFound("nni-intreface-id",
2498 log.Fields{
2499 "classifier": classifier,
2500 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002501 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302502 }
2503
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002504 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002505 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002506 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002507 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002508
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002509 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2510 log.Fields{
2511 "classifier": classifier,
2512 "action": action,
2513 "flowId": logicalFlow.Id,
2514 "intf-id": networkInterfaceID})
2515
David K. Bainbridge794735f2020-02-11 21:01:37 -08002516 classifierProto, err := makeOpenOltClassifierField(classifier)
2517 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002518 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002519 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002520 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002521 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002522 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002523 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002524 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002525 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002526 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2527 OnuId: int32(onuID), // OnuId not required
2528 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002529 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002530 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002531 AllocId: int32(allocID), // AllocId not used
2532 NetworkIntfId: int32(networkInterfaceID),
2533 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002534 Classifier: classifierProto,
2535 Action: actionProto,
2536 Priority: int32(logicalFlow.Priority),
2537 Cookie: logicalFlow.Cookie,
2538 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002539 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002540 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002541 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002542 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002543 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002544}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002545
Esin Karamanae41e2b2019-12-17 18:13:13 +00002546//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2547func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2548 var packetType string
2549 ovid, ivid := false, false
2550 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2551 vid := vlanID & VlanvIDMask
2552 if vid != ReservedVlan {
2553 ovid = true
2554 }
2555 }
2556 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2557 vid := uint32(metadata)
2558 if vid != ReservedVlan {
2559 ivid = true
2560 }
2561 }
2562 if ovid && ivid {
2563 packetType = DoubleTag
2564 } else if !ovid && !ivid {
2565 packetType = Untagged
2566 } else {
2567 packetType = SingleTag
2568 }
2569 return packetType
2570}
2571
2572//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002573func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002574 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002575 action := make(map[string]interface{})
2576 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2577 action[TrapToHost] = true
2578 /* We manage flowId resource pool on per PON port basis.
2579 Since this situation is tricky, as a hack, we pass the NNI port
2580 index (network_intf_id) as PON port Index for the flowId resource
2581 pool. Also, there is no ONU Id available for trapping packets
2582 on NNI port, use onu_id as -1 (invalid)
2583 ****************** CAVEAT *******************
2584 This logic works if the NNI Port Id falls within the same valid
2585 range of PON Port Ids. If this doesn't work for some OLT Vendor
2586 we need to have a re-look at this.
2587 *********************************************
2588 */
2589 onuID := -1
2590 uniID := -1
2591 gemPortID := -1
2592 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002593 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002594 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302595 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002596 "classifier": classifier,
2597 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002598 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002599 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002600 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002601 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002602 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002603 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002604
David K. Bainbridge794735f2020-02-11 21:01:37 -08002605 classifierProto, err := makeOpenOltClassifierField(classifier)
2606 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002607 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002608 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002609 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002610 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002611 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002612 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002613 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002614 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002615 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2616 OnuId: int32(onuID), // OnuId not required
2617 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002618 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002619 FlowType: Downstream,
2620 AllocId: int32(allocID), // AllocId not used
2621 NetworkIntfId: int32(networkInterfaceID),
2622 GemportId: int32(gemPortID), // GemportId not used
2623 Classifier: classifierProto,
2624 Action: actionProto,
2625 Priority: int32(logicalFlow.Priority),
2626 Cookie: logicalFlow.Cookie,
2627 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002628 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002629 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002630 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002631 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002632
David K. Bainbridge794735f2020-02-11 21:01:37 -08002633 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002634}
2635
salmansiddiqui7ac62132019-08-22 03:58:50 +00002636func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2637 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302638 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002639 }
2640 if Dir == tp_pb.Direction_UPSTREAM {
2641 return "upstream", nil
2642 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2643 return "downstream", nil
2644 }
2645 return "", nil
2646}
2647
Kent Hagermane6ff1012020-07-14 15:07:53 -04002648// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302649func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002650 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002651 tpID uint32, uni string) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002652 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002653 intfID := args[IntfID]
2654 onuID := args[OnuID]
2655 uniID := args[UniID]
2656 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002657 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002658 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002659 gemToAes := make(map[uint32]bool)
2660
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002661 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002662 var direction = tp_pb.Direction_UPSTREAM
2663 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002664 case *tp_pb.TechProfileInstance:
Gamze Abaka7650be62021-02-26 10:50:36 +00002665 if IsUpstream(actionInfo[Output].(uint32)) {
2666 attributes = TpInst.UpstreamGemPortAttributeList
2667 } else {
2668 attributes = TpInst.DownstreamGemPortAttributeList
2669 direction = tp_pb.Direction_DOWNSTREAM
2670 }
2671 default:
2672 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
2673 return
2674 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002675
2676 if len(gemPorts) == 1 {
2677 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002678 gemPortID = gemPorts[0]
2679 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002680 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2681 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002682 pBitMap := attributes[idx].PbitMap
2683 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2684 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2685 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
2686 // this pcp bit traffic.
2687 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2688 if pbitSet == pbit1 {
2689 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2690 pbitToGem[pcp] = gemID
2691 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002692 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002693 }
2694 }
2695 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002696 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2697 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2698 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002699 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002700 }
2701
Gamze Abaka7650be62021-02-26 10:50:36 +00002702 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2703 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2704
salmansiddiqui7ac62132019-08-22 03:58:50 +00002705 if ipProto, ok := classifierInfo[IPProto]; ok {
2706 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002707 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002708 "tp-id": tpID,
2709 "alloc-id": allocID,
2710 "intf-id": intfID,
2711 "onu-id": onuID,
2712 "uni-id": uniID,
2713 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002714 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002715 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002716 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002717 }
2718
Girish Gowdra32625212020-04-29 11:26:35 -07002719 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002720 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302721 log.Fields{
2722 "intf-id": intfID,
2723 "onu-id": onuID,
2724 "uni-id": uniID,
2725 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002726 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002727 logger.Warn(ctx, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002728 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002729 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002730 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002731 return
2732 }
2733 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002734 if ethType.(uint32) == EapEthType {
2735 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002736 "intf-id": intfID,
2737 "onu-id": onuID,
2738 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002739 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002740 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002741 var vlanID uint32
2742 if val, ok := classifierInfo[VlanVid]; ok {
2743 vlanID = (val.(uint32)) & VlanvIDMask
2744 } else {
2745 vlanID = DefaultMgmtVlan
2746 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002747 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002748 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002749 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002750 } else if ethType.(uint32) == PPPoEDEthType {
2751 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2752 "tp-id": tpID,
2753 "alloc-id": allocID,
2754 "intf-id": intfID,
2755 "onu-id": onuID,
2756 "uni-id": uniID,
2757 })
2758 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002759 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002760 logger.Warn(ctx, err)
2761 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002762 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002763 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002764 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002765 "intf-id": intfID,
2766 "onu-id": onuID,
2767 "uni-id": uniID,
2768 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002769 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002770 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002771 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002772 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002773 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002774 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002775 "intf-id": intfID,
2776 "onu-id": onuID,
2777 "uni-id": uniID,
2778 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002779 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002780 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002781 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002782 }
2783 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002784 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05302785 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002786 "intf-id": intfID,
2787 "onu-id": onuID,
2788 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05302789 "classifier": classifierInfo,
2790 "action": actionInfo,
2791 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002792 return
2793 }
2794 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002795 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002796 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002797 logger.Warn(ctx, err)
2798 }
2799 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002800}
2801
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002802func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002803 f.gemToFlowIDsKey.RLock()
2804 flowIDList := f.gemToFlowIDs[gemPortID]
2805 f.gemToFlowIDsKey.RUnlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002806 return len(flowIDList) > 1
2807
Gamze Abakafee36392019-10-03 11:17:24 +00002808}
2809
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002810func (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 +05302811 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002812 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2813 for _, currentGemPort := range currentGemPorts {
2814 for _, tpGemPort := range tpGemPorts {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002815 if (currentGemPort == tpGemPort.GemportId) && (currentGemPort != gemPortID) {
Gamze Abakafee36392019-10-03 11:17:24 +00002816 return true, currentGemPort
2817 }
2818 }
2819 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00002820 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
2821 return false, 0
2822}
Girish Gowdra54934262019-11-13 14:19:55 +05302823
Gamze Abakacb0e6772021-06-10 08:32:12 +00002824func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002825 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
2826 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
2827 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 +00002828 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05302829 for i := 0; i < len(tpInstances); i++ {
2830 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00002831 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002832 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Gamze Abakacb0e6772021-06-10 08:32:12 +00002833 logger.Debugw(ctx, "alloc-is-in-use",
2834 log.Fields{
2835 "device-id": f.deviceHandler.device.Id,
2836 "intfID": sq.intfID,
2837 "onuID": sq.onuID,
2838 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002839 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00002840 })
2841 return true
Girish Gowdra54934262019-11-13 14:19:55 +05302842 }
2843 }
2844 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00002845 return false
Gamze Abakafee36392019-10-03 11:17:24 +00002846}
2847
Neha Sharma96b7bf22020-06-15 10:37:32 +00002848func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002849 for _, field := range flows.GetOfbFields(flow) {
2850 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002851 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002852 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002853 } else if field.Type == flows.ETH_DST {
2854 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002855 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07002856 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002857 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002858 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002859 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002860 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002861 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002862 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05302863 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00002864 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002865 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002866 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002867 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002868 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002869 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002870 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002871 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002872 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002873 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002874 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002875 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002876 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002877 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002878 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002879 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002880 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002881 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002882 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07002883 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002884 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002885 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002886 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002887 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002888 return
2889 }
2890 }
2891}
2892
Neha Sharma96b7bf22020-06-15 10:37:32 +00002893func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07002894 for _, action := range flows.GetActions(flow) {
2895 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002896 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002897 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002898 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002899 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002900 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002901 }
Scott Baker355d1742019-10-24 10:57:52 -07002902 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002903 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00002904 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002905 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002906 if out := action.GetPush(); out != nil {
2907 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002908 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002909 } else {
2910 actionInfo[PushVlan] = true
2911 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00002912 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05302913 log.Fields{
2914 "push-tpid": actionInfo[TPID].(uint32),
2915 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002916 }
2917 }
Scott Baker355d1742019-10-24 10:57:52 -07002918 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002919 if out := action.GetSetField(); out != nil {
2920 if field := out.GetField(); field != nil {
2921 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00002922 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002923 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002924 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
2925 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002926 }
2927 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002928 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002929 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002930 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002931 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002932 }
2933 }
2934 return nil
2935}
2936
Neha Sharma96b7bf22020-06-15 10:37:32 +00002937func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00002938 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00002939 fieldtype := ofbField.GetType()
2940 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00002941 if vlan := ofbField.GetVlanVid(); vlan != 0 {
2942 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00002943 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002944 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002945 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00002946 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00002947 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
2948 pcp := ofbField.GetVlanPcp()
2949 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002950 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002951 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002952 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00002953 }
2954 }
2955}
2956
Neha Sharma96b7bf22020-06-15 10:37:32 +00002957func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00002958 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002959 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00002960 } else {
2961 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00002962 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002963 }
2964}
2965
Neha Sharma96b7bf22020-06-15 10:37:32 +00002966func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002967 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002968 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002969 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2970 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002971 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002972 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00002973 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05302974 log.Fields{
2975 "newinport": classifierInfo[InPort].(uint32),
2976 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002977 } else {
Shrey Baid26912972020-04-16 21:02:31 +05302978 return olterrors.NewErrNotFound("child-in-port",
2979 log.Fields{
2980 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
2981 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002982 }
2983 }
2984 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002985 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002986 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07002987 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002988 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002989 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00002990 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05302991 log.Fields{
2992 "newoutport": actionInfo[Output].(uint32),
2993 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002994 } else {
Shrey Baid26912972020-04-16 21:02:31 +05302995 return olterrors.NewErrNotFound("out-port",
2996 log.Fields{
2997 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
2998 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002999 }
3000 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3001 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003002 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003003 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003004 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303005 log.Fields{
3006 "newinport": actionInfo[Output].(uint32),
3007 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003008 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303009 return olterrors.NewErrNotFound("nni-port",
3010 log.Fields{
3011 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3012 "in-port": classifierInfo[InPort].(uint32),
3013 "out-port": actionInfo[Output].(uint32),
3014 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003015 }
3016 }
3017 }
3018 return nil
3019}
Gamze Abakafee36392019-10-03 11:17:24 +00003020
Neha Sharma96b7bf22020-06-15 10:37:32 +00003021func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003022 /* Metadata 8 bytes:
3023 Most Significant 2 Bytes = Inner VLAN
3024 Next 2 Bytes = Tech Profile ID(TPID)
3025 Least Significant 4 Bytes = Port ID
3026 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3027 subscriber related flows.
3028 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003029 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003030 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003031 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003032 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003033 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003034 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003035}
3036
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003037func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3038 for _, sliceElement := range slice {
3039 if sliceElement == item {
3040 return slice
3041 }
3042 }
3043 return append(slice, item)
3044}
3045
3046func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003047 for _, sliceElement := range slice {
3048 if sliceElement == item {
3049 return slice
3050 }
3051 }
3052 return append(slice, item)
3053}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303054
3055// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003056func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303057
3058 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3059 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003060 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003061 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003062 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003063 log.Fields{
3064 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003065 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003066 return uint32(0), err
3067 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003068 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303069 return intfID, nil
3070 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003071 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(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-classifier-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, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303080 return intfID, nil
3081 }
3082 return uint32(0), nil
3083}
3084
3085// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003086func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3087 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3088 if err != nil {
3089 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3090 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3091 return
3092 }
3093 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003094
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003095 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003096 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003097 f.packetInGemPortLock.RUnlock()
3098
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303099 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003100 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003101 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 +05303102 log.Fields{
3103 "pktinkey": pktInkey,
3104 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003105 return
3106 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303107 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003108 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003109 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003110 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003111
npujarec5762e2020-01-01 14:08:48 +05303112 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003113 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 +05303114 log.Fields{
3115 "pktinkey": pktInkey,
3116 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303117}
3118
Esin Karaman7fb80c22020-07-16 14:23:33 +00003119//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3120func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3121 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003122 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003123 return 0, 0, errors.New("invalid packet length")
3124 }
3125 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3126 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3127
3128 var index int8
3129 if outerEthType == 0x8100 {
3130 if innerEthType == 0x8100 {
3131 // q-in-q 802.1ad or 802.1q double tagged packet.
3132 // get the inner vlanId
3133 index = 18
3134 } else {
3135 index = 14
3136 }
3137 priority := (packet[index] >> 5) & 0x7
3138 //13 bits composes vlanId value
3139 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3140 return vlan, priority, nil
3141 }
3142 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3143 return 0, 0, nil
3144}
3145
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003146func (f *OpenOltFlowMgr) loadFlowIDsForGemAndGemIDsForFlow(ctx context.Context) {
3147 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - start")
3148 f.onuGemInfoLock.RLock()
3149 f.gemToFlowIDsKey.Lock()
3150 f.flowIDToGemsLock.Lock()
3151 for _, og := range f.onuGemInfoMap {
3152 for _, gem := range og.GemPorts {
3153 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, f.ponPortIdx, gem)
3154 if err != nil {
3155 f.gemToFlowIDs[gem] = flowIDs
3156 for _, flowID := range flowIDs {
3157 if _, ok := f.flowIDToGems[flowID]; !ok {
3158 f.flowIDToGems[flowID] = []uint32{gem}
3159 } else {
3160 f.flowIDToGems[flowID] = appendUnique32bit(f.flowIDToGems[flowID], gem)
3161 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303162 }
3163 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303164 }
3165 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003166 f.flowIDToGemsLock.Unlock()
3167 f.gemToFlowIDsKey.Unlock()
3168 f.onuGemInfoLock.RUnlock()
3169 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - end")
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303170}
Esin Karamanccb714b2019-11-29 15:02:06 +00003171
Girish Gowdra9602eb42020-09-09 15:50:39 -07003172//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3173// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003174func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003175 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003176 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3177 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003178 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003179 "flow-id": flow.Id,
3180 "device-id": f.deviceHandler.device.Id})
3181 // Remove from device
3182 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3183 // DKB
3184 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3185 log.Fields{
3186 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003187 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003188 return err
3189 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003190
3191 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003192}
3193
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003194func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, ponID uint32, onuID uint32, uniID uint32) *ic.InterAdapterTechProfileDownloadMessage {
3195 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003196 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003197 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
3198 return nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003199 }
3200
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003201 switch tpInst := tpInst.(type) {
3202 case *tp_pb.TechProfileInstance:
3203 logger.Debugw(ctx, "fetched-tp-instance-successfully--formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
3204 return &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID,
3205 TpInstancePath: tpPath,
3206 TechTpInstance: &ic.InterAdapterTechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003207 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003208 case *openoltpb2.EponTechProfileInstance:
3209 return &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID,
3210 TpInstancePath: tpPath,
3211 TechTpInstance: &ic.InterAdapterTechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
3212 }
3213 default:
3214 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003215 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003216 return nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003217}
3218
Girish Gowdrabcf98af2021-07-01 08:24:42 -07003219func (f *OpenOltFlowMgr) getOnuGemInfoList(ctx context.Context) []rsrcMgr.OnuGemInfo {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003220 var onuGemInfoLst []rsrcMgr.OnuGemInfo
3221 f.onuGemInfoLock.RLock()
3222 defer f.onuGemInfoLock.RUnlock()
3223 for _, v := range f.onuGemInfoMap {
3224 onuGemInfoLst = append(onuGemInfoLst, *v)
3225 }
3226 return onuGemInfoLst
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003227}