blob: 1f4b1164d52e9c40ee095d6f70123188eb89e4ac [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 Gowdra4c3d4602021-07-22 16:33:37 -070025 "github.com/opencord/voltha-lib-go/v6/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 Gowdra4c3d4602021-07-22 16:33:37 -070031 "github.com/opencord/voltha-lib-go/v6/pkg/flows"
32 "github.com/opencord/voltha-lib-go/v6/pkg/log"
33 tp "github.com/opencord/voltha-lib-go/v6/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 Gowdra4c3d4602021-07-22 16:33:37 -0700854 var err error
855 f.techprofile, err = tp.NewTechProfile(ctx, f.resourceMgr.PonRsrMgr, f.resourceMgr.PonRsrMgr.Backend,
856 f.resourceMgr.PonRsrMgr.Address, f.deviceHandler.cm.Backend.PathPrefix)
857 if err != nil || f.techprofile == nil {
858 logger.Errorw(ctx, "failed-to-allocate-to-techprofile-for-pon-port", log.Fields{"intfID": intfID, "err": err})
859 return fmt.Errorf("failed-to-allocate-tech-profile-for-pon-port--pon-%v-err-%v", intfID, err)
860 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400861 tpCount++
Neha Sharma96b7bf22020-06-15 10:37:32 +0000862 logger.Debugw(ctx, "init-tech-profile-done",
Shrey Baid26912972020-04-16 21:02:31 +0530863 log.Fields{
864 "intf-id": intfID,
865 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530866 }
867 }
868 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400869 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530870 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530871 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800872 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530873 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
874 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530875 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000876 logger.Infow(ctx, "populated-techprofile-for-ponports-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530877 log.Fields{
878 "numofTech": tpCount,
879 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
880 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530881 return nil
882}
883
Gamze Abaka7650be62021-02-26 10:50:36 +0000884func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
885 flowContext.classifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000886 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530887 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000888 "uplinkClassifier": flowContext.classifier,
889 "uplinkAction": flowContext.action})
890 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
Manikkaraj k884c1242019-04-11 16:26:42 +0530891 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530892}
893
Gamze Abaka7650be62021-02-26 10:50:36 +0000894func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
895 downlinkClassifier := flowContext.classifier
896 downlinkAction := flowContext.action
897
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700898 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000899 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530900 log.Fields{
901 "downlinkClassifier": downlinkClassifier,
902 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400903 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
904 if vlan, exists := downlinkClassifier[VlanVid]; exists {
905 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700906 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Gamze Abaka7650be62021-02-26 10:50:36 +0000907 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, flowContext.intfID, flowContext.onuID, flowContext.uniID) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000908 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530909 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000910 "flow": flowContext.logicalFlow,
Shrey Baid26912972020-04-16 21:02:31 +0530911 "device-id": f.deviceHandler.device.Id,
Gamze Abaka7650be62021-02-26 10:50:36 +0000912 "onu-id": flowContext.onuID,
913 "intf-id": flowContext.intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800914 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400915 }
916 }
917 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530918 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400919
Manikkaraj k884c1242019-04-11 16:26:42 +0530920 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700921 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400922 // vlan_vid is a uint32. must be type asserted as such or conversion fails
923 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530924 if ok {
925 downlinkAction[VlanVid] = dlClVid & 0xfff
926 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530927 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530928 "reason": "failed-to-convert-vlanid-classifier",
929 "vlan-id": VlanVid,
930 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530931 }
932
Gamze Abaka7650be62021-02-26 10:50:36 +0000933 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +0530934}
935
Gamze Abaka7650be62021-02-26 10:50:36 +0000936func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700937
Gamze Abaka7650be62021-02-26 10:50:36 +0000938 intfID := flowContext.intfID
939 onuID := flowContext.onuID
940 uniID := flowContext.uniID
941 classifier := flowContext.classifier
942 action := flowContext.action
943 allocID := flowContext.allocID
944 gemPortID := flowContext.gemPortID
945 tpID := flowContext.tpID
946 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +0000947 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530948 log.Fields{
949 "intf-id": intfID,
950 "onu-id": onuID,
951 "uni-id": uniID,
952 "device-id": f.deviceHandler.device.Id,
953 "classifier": classifier,
954 "action": action,
955 "direction": direction,
956 "alloc-id": allocID,
957 "gemport-id": gemPortID,
958 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700959
960 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000961 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +0530962 log.Fields{
963 "device-id": f.deviceHandler.device.Id,
964 "intf-id": intfID,
965 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800966 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530967 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800968 classifierProto, err := makeOpenOltClassifierField(classifier)
969 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530970 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530971 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000972 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +0530973 log.Fields{
974 "classifier": *classifierProto,
975 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +0000976 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800977 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530978 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530979 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000980 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +0530981 log.Fields{
982 "action": *actionProto,
983 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +0000984 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530985 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530986 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800987 log.Fields{
988 "classifier": classifier,
989 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +0530990 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800991 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530992 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700993
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700994 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700995 OnuId: int32(onuID),
996 UniId: int32(uniID),
997 FlowId: logicalFlow.Id,
998 FlowType: direction,
999 AllocId: int32(allocID),
1000 NetworkIntfId: int32(networkIntfID),
1001 GemportId: int32(gemPortID),
1002 Classifier: classifierProto,
1003 Action: actionProto,
1004 Priority: int32(logicalFlow.Priority),
1005 Cookie: logicalFlow.Cookie,
1006 PortNo: flowContext.portNo,
1007 TechProfileId: tpID,
1008 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1009 PbitToGemport: flowContext.pbitToGem,
1010 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001011 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001012 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001013 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301014 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001015 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301016 log.Fields{"direction": direction,
1017 "device-id": f.deviceHandler.device.Id,
1018 "flow": flow,
1019 "intf-id": intfID,
1020 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001021
David K. Bainbridge794735f2020-02-11 21:01:37 -08001022 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301023}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001024
Gamze Abaka7650be62021-02-26 10:50:36 +00001025func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1026
1027 intfID := flowContext.intfID
1028 onuID := flowContext.onuID
1029 uniID := flowContext.uniID
1030 logicalFlow := flowContext.logicalFlow
1031 classifier := flowContext.classifier
1032 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301033
Neha Sharma96b7bf22020-06-15 10:37:32 +00001034 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301035 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301036 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001037 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301038 "action": action,
1039 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001040 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301041 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301042
1043 // Clear the action map
1044 for k := range action {
1045 delete(action, k)
1046 }
1047
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001048 action[TrapToHost] = true
1049 classifier[UDPSrc] = uint32(68)
1050 classifier[UDPDst] = uint32(67)
1051 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301052
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001053 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001054 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301055 log.Fields{
1056 "device-id": f.deviceHandler.device.Id,
1057 "intf-id": intfID,
1058 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001059 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301060 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301061
Neha Sharma96b7bf22020-06-15 10:37:32 +00001062 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301063 log.Fields{
1064 "ul_classifier": classifier,
1065 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001066 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301067 "intf-id": intfID,
1068 "onu-id": onuID,
1069 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301070
David K. Bainbridge794735f2020-02-11 21:01:37 -08001071 classifierProto, err := makeOpenOltClassifierField(classifier)
1072 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301073 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301074 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001075 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001076 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001077 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301078 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301079 }
1080
David K. Bainbridge794735f2020-02-11 21:01:37 -08001081 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001082 OnuId: int32(onuID),
1083 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001084 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001085 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001086 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001087 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001088 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301089 Classifier: classifierProto,
1090 Action: actionProto,
1091 Priority: int32(logicalFlow.Priority),
1092 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001093 PortNo: flowContext.portNo,
1094 TechProfileId: flowContext.tpID,
1095 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1096 PbitToGemport: flowContext.pbitToGem,
1097 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001098 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001099 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001100 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001101 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001102 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301103 log.Fields{
1104 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001105 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301106 "intf-id": intfID,
1107 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301108
David K. Bainbridge794735f2020-02-11 21:01:37 -08001109 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301110}
1111
Esin Karamanae41e2b2019-12-17 18:13:13 +00001112//addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001113func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1114 delete(flowContext.classifier, VlanVid)
1115 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001116}
1117
1118//addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001119func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1120
1121 intfID := flowContext.intfID
1122 onuID := flowContext.onuID
1123 uniID := flowContext.uniID
1124 logicalFlow := flowContext.logicalFlow
1125 classifier := flowContext.classifier
1126 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001127
Neha Sharma96b7bf22020-06-15 10:37:32 +00001128 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001129 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301130 return olterrors.NewErrNotFound("nni-interface-id",
1131 log.Fields{
1132 "classifier": classifier,
1133 "action": action,
1134 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001135 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001136 }
1137
1138 // Clear the action map
1139 for k := range action {
1140 delete(action, k)
1141 }
1142
1143 action[TrapToHost] = true
1144 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001145
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001146 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001147 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001148 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001149 }
1150
Neha Sharma96b7bf22020-06-15 10:37:32 +00001151 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301152 log.Fields{
1153 "ul_classifier": classifier,
1154 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001155 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301156 "device-id": f.deviceHandler.device.Id,
1157 "intf-id": intfID,
1158 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001159
David K. Bainbridge794735f2020-02-11 21:01:37 -08001160 classifierProto, err := makeOpenOltClassifierField(classifier)
1161 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301162 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001163 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001164 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301165 log.Fields{
1166 "classifier": *classifierProto,
1167 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001168 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001169 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301170 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001171 }
1172
David K. Bainbridge794735f2020-02-11 21:01:37 -08001173 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001174 OnuId: int32(onuID),
1175 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001176 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001177 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001178 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001179 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001180 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001181 Classifier: classifierProto,
1182 Action: actionProto,
1183 Priority: int32(logicalFlow.Priority),
1184 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001185 PortNo: flowContext.portNo,
1186 TechProfileId: flowContext.tpID,
1187 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1188 PbitToGemport: flowContext.pbitToGem,
1189 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001190 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001191
David K. Bainbridge794735f2020-02-11 21:01:37 -08001192 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001193 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 -08001194 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001195
David K. Bainbridge794735f2020-02-11 21:01:37 -08001196 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001197}
1198
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001199// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001200func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1201 intfID := flowContext.intfID
1202 onuID := flowContext.onuID
1203 uniID := flowContext.uniID
1204 portNo := flowContext.portNo
1205 allocID := flowContext.allocID
1206 gemPortID := flowContext.gemPortID
1207 logicalFlow := flowContext.logicalFlow
1208 classifier := flowContext.classifier
1209 action := flowContext.action
1210
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001211 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301212 log.Fields{
1213 "intf-id": intfID,
1214 "onu-id": onuID,
1215 "port-no": portNo,
1216 "alloc-id": allocID,
1217 "gemport-id": gemPortID,
1218 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001219 "flow": logicalFlow,
1220 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301221
1222 uplinkClassifier := make(map[string]interface{})
1223 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301224
manikkaraj kbf256be2019-03-25 00:13:48 +05301225 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001226 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001227 uplinkClassifier[PacketTagType] = SingleTag
1228 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001229 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301230 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001231 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001232 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001233 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301234 "device-id": f.deviceHandler.device.Id,
1235 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001236 "intf-id": intfID,
1237 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001238 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301239 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001240 //Add Uplink EthType Flow
1241 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301242 log.Fields{
1243 "ul_classifier": uplinkClassifier,
1244 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001245 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301246 "device-id": f.deviceHandler.device.Id,
1247 "intf-id": intfID,
1248 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301249
David K. Bainbridge794735f2020-02-11 21:01:37 -08001250 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1251 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301252 return olterrors.NewErrInvalidValue(log.Fields{
1253 "classifier": uplinkClassifier,
1254 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301255 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001256 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301257 log.Fields{
1258 "classifier": *classifierProto,
1259 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001260 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001261 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301262 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301263 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001264 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301265 log.Fields{
1266 "action": *actionProto,
1267 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001268 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301269 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301270 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001271 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301272 "action": action,
1273 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001274 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301275 }
1276
David K. Bainbridge794735f2020-02-11 21:01:37 -08001277 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001278 OnuId: int32(onuID),
1279 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001280 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001281 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001282 AllocId: int32(allocID),
1283 NetworkIntfId: int32(networkIntfID),
1284 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301285 Classifier: classifierProto,
1286 Action: actionProto,
1287 Priority: int32(logicalFlow.Priority),
1288 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001289 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001290 TechProfileId: flowContext.tpID,
1291 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1292 PbitToGemport: flowContext.pbitToGem,
1293 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001294 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001295 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001296 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001297 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001298 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301299 log.Fields{
1300 "device-id": f.deviceHandler.device.Id,
1301 "onu-id": onuID,
1302 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001303 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301304 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001305
David K. Bainbridge794735f2020-02-11 21:01:37 -08001306 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301307}
1308
David K. Bainbridge794735f2020-02-11 21:01:37 -08001309func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001310 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001311
1312 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1313 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1314 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001315 if vlanID != ReservedVlan {
1316 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001317 classifier.OVid = vid
1318 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301319 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001320 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1321 vid := uint32(metadata)
1322 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001323 classifier.IVid = vid
1324 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301325 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301326 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001327 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301328 classifier.OPbits = vlanPcp
1329 } else {
1330 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301331 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001332 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1333 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1334 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1335 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001336 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001337 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1338 classifier.PktTagType = pktTagType
1339
1340 switch pktTagType {
1341 case SingleTag:
1342 case DoubleTag:
1343 case Untagged:
1344 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001345 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301346 }
1347 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001348 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301349}
1350
Gamze Abaka724d0852020-03-18 12:10:24 +00001351func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001352 var actionCmd openoltpb2.ActionCmd
1353 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301354 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001355 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301356 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001357 if _, ok := actionInfo[VlanPcp]; ok {
1358 action.Cmd.RemarkInnerPbits = true
1359 action.IPbits = actionInfo[VlanPcp].(uint32)
1360 if _, ok := actionInfo[VlanVid]; ok {
1361 action.Cmd.TranslateInnerTag = true
1362 action.IVid = actionInfo[VlanVid].(uint32)
1363 }
1364 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001365 } else if _, ok := actionInfo[PushVlan]; ok {
1366 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301367 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001368 if _, ok := actionInfo[VlanPcp]; ok {
1369 action.OPbits = actionInfo[VlanPcp].(uint32)
1370 action.Cmd.RemarkOuterPbits = true
1371 if _, ok := classifierInfo[VlanVid]; ok {
1372 action.IVid = classifierInfo[VlanVid].(uint32)
1373 action.Cmd.TranslateInnerTag = true
1374 }
1375 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001376 } else if _, ok := actionInfo[TrapToHost]; ok {
1377 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301378 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001379 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301380 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001381 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301382}
1383
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001384// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001385func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001386 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301387}
1388
Gamze Abakafee36392019-10-03 11:17:24 +00001389// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001390func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301391 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001392 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1393
Gamze Abakafee36392019-10-03 11:17:24 +00001394 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301395 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001396 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301397 // return err
1398 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001399 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001400 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 +00001401 }
1402 return nil
1403}
1404
1405// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301406func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001407 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001408 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001409 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001410 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301411 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1412 log.Fields{
1413 "tp-id": tpID,
1414 "uni-port-name": uniPortName,
1415 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001416 }
1417 return nil
1418}
1419
David K. Bainbridge794735f2020-02-11 21:01:37 -08001420func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001421
1422 var intfID uint32
1423 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1424 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1425 */
1426 if deviceFlow.AccessIntfId != -1 {
1427 intfID = uint32(deviceFlow.AccessIntfId)
1428 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001429 // We need to log the valid interface ID.
1430 // 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 +00001431 intfID = uint32(deviceFlow.NetworkIntfId)
1432 }
1433
Neha Sharma96b7bf22020-06-15 10:37:32 +00001434 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301435 "flow": *deviceFlow,
1436 "device-id": f.deviceHandler.device.Id,
1437 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001438 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001439
1440 st, _ := status.FromError(err)
1441 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001442 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001443 "err": err,
1444 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301445 "device-id": f.deviceHandler.device.Id,
1446 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001447 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301448 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001449
1450 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001451 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301452 log.Fields{"err": err,
1453 "device-flow": deviceFlow,
1454 "device-id": f.deviceHandler.device.Id,
1455 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001456 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001457 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001458 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301459 log.Fields{
1460 "flow": *deviceFlow,
1461 "device-id": f.deviceHandler.device.Id,
1462 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001463
1464 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1465 if deviceFlow.AccessIntfId != -1 {
1466 // No need to register the flow if it is a trap on nni flow.
1467 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1468 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1469 return err
1470 }
1471 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001472 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001473}
1474
Neha Sharma96b7bf22020-06-15 10:37:32 +00001475func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1476 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301477 log.Fields{
1478 "flow": *deviceFlow,
1479 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001480 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001481 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001482 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001483 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301484 log.Fields{
1485 "err": err,
1486 "deviceFlow": deviceFlow,
1487 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001488 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001489 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001490 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001491 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001492
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001493 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001494 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001495 "of-flow-id": ofFlowID,
1496 "flow": *deviceFlow,
1497 "device-id": f.deviceHandler.device.Id,
1498 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001499 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301500}
1501
David K. Bainbridge794735f2020-02-11 21:01:37 -08001502func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001503
1504 classifierInfo := make(map[string]interface{})
1505 actionInfo := make(map[string]interface{})
1506
1507 classifierInfo[EthType] = uint32(LldpEthType)
1508 classifierInfo[PacketTagType] = Untagged
1509 actionInfo[TrapToHost] = true
1510
1511 // LLDP flow is installed to trap LLDP packets on the NNI port.
1512 // We manage flow_id resource pool on per PON port basis.
1513 // Since this situation is tricky, as a hack, we pass the NNI port
1514 // index (network_intf_id) as PON port Index for the flow_id resource
1515 // pool. Also, there is no ONU Id available for trapping LLDP packets
1516 // on NNI port, use onu_id as -1 (invalid)
1517 // ****************** CAVEAT *******************
1518 // This logic works if the NNI Port Id falls within the same valid
1519 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1520 // we need to have a re-look at this.
1521 // *********************************************
1522
1523 var onuID = -1
1524 var uniID = -1
1525 var gemPortID = -1
1526
Neha Sharma96b7bf22020-06-15 10:37:32 +00001527 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001528 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301529 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001530 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001531 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001532 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001533 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001534 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001535
David K. Bainbridge794735f2020-02-11 21:01:37 -08001536 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1537 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301538 return olterrors.NewErrInvalidValue(
1539 log.Fields{
1540 "classifier": classifierInfo,
1541 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001542 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001543 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301544 log.Fields{
1545 "classifier": *classifierProto,
1546 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001547 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001548 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301549 return olterrors.NewErrInvalidValue(
1550 log.Fields{
1551 "action": actionInfo,
1552 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001553 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001554 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301555 log.Fields{
1556 "action": *actionProto,
1557 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001558
1559 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1560 OnuId: int32(onuID), // OnuId not required
1561 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001562 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001563 FlowType: Downstream,
1564 NetworkIntfId: int32(networkInterfaceID),
1565 GemportId: int32(gemPortID),
1566 Classifier: classifierProto,
1567 Action: actionProto,
1568 Priority: int32(flow.Priority),
1569 Cookie: flow.Cookie,
1570 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001571 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001572 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301573 log.Fields{
1574 "flow": downstreamflow,
1575 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001576 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001577 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301578 log.Fields{
1579 "device-id": f.deviceHandler.device.Id,
1580 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001581 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001582
David K. Bainbridge794735f2020-02-11 21:01:37 -08001583 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301584}
1585
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001586func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1587 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001588}
1589
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001590//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001591func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001592 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1593 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1594 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001595 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301596 log.Fields{
1597 "intf-id": intfID,
1598 "onu-id": onuID,
1599 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001600 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001601 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301602 return nil, olterrors.NewErrNotFound("onu-child-device",
1603 log.Fields{
1604 "onu-id": onuID,
1605 "intf-id": intfID,
1606 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001607 }
1608 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1609 //better to ad the device to cache here.
1610 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1611 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001612 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301613 log.Fields{
1614 "intf-id": intfID,
1615 "onu-id": onuID,
1616 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001617 }
1618
1619 return onuDev.(*OnuDevice), nil
1620}
1621
1622//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001623func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1624 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301625 log.Fields{
1626 "pon-port": intfID,
1627 "onu-id": onuID,
1628 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001629 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001630 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001631 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301632 return nil, olterrors.NewErrNotFound("onu",
1633 log.Fields{
1634 "interface-id": parentPortNo,
1635 "onu-id": onuID,
1636 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001637 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301638 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001639 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301640 log.Fields{
1641 "device-id": f.deviceHandler.device.Id,
1642 "child_device_id": onuDevice.Id,
1643 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301644 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301645}
1646
Neha Sharma96b7bf22020-06-15 10:37:32 +00001647func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1648 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301649 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001650 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301651 log.Fields{
1652 "intf-id": intfID,
1653 "onu-id": onuID,
1654 "uni-id": uniID,
1655 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001656 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301657 }
1658
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001659 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpInstancePath: tpPath, GemPortId: gemPortID}
1660 logger.Infow(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301661 log.Fields{
1662 "msg": *delGemPortMsg,
1663 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001664 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301665 delGemPortMsg,
1666 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001667 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001668 onuDev.deviceType,
1669 onuDev.deviceID,
1670 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301671 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1672 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001673 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301674 "to-adapter": onuDev.deviceType,
1675 "onu-id": onuDev.deviceID,
1676 "proxyDeviceID": onuDev.proxyDeviceID,
1677 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301678 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001679 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301680 log.Fields{
1681 "msg": delGemPortMsg,
1682 "from-adapter": f.deviceHandler.device.Type,
1683 "to-adapter": onuDev.deviceType,
1684 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301685 return nil
1686}
1687
Neha Sharma96b7bf22020-06-15 10:37:32 +00001688func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1689 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301690 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001691 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301692 log.Fields{
1693 "intf-id": intfID,
1694 "onu-id": onuID,
1695 "uni-id": uniID,
1696 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001697 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301698 }
1699
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001700 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpInstancePath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001701 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301702 log.Fields{
1703 "msg": *delTcontMsg,
1704 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001705 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301706 delTcontMsg,
1707 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001708 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001709 onuDev.deviceType,
1710 onuDev.deviceID,
1711 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301712 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1713 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001714 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301715 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1716 "proxyDeviceID": onuDev.proxyDeviceID,
1717 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301718 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001719 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301720 log.Fields{
1721 "msg": delTcontMsg,
1722 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301723 return nil
1724}
1725
Girish Gowdrac3037402020-01-22 20:29:53 +05301726// Once the gemport is released for a given onu, it also has to be cleared from local cache
1727// which was used for deriving the gemport->logicalPortNo during packet-in.
1728// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1729// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001730func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001731 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301732 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001733 "gem-port-id": gemPortID,
1734 "intf-id": intfID,
1735 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001736 "device-id": f.deviceHandler.device.Id})
1737 f.onuGemInfoLock.RLock()
1738 onugem, ok := f.onuGemInfoMap[onuID]
1739 f.onuGemInfoLock.RUnlock()
1740 if !ok {
1741 logger.Warnw(ctx, "onu gem info already cleared from cache", log.Fields{
1742 "gem-port-id": gemPortID,
1743 "intf-id": intfID,
1744 "onu-id": onuID,
1745 "device-id": f.deviceHandler.device.Id})
1746 return
1747 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001748deleteLoop:
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001749 for j, gem := range onugem.GemPorts {
1750 // If the gemport is found, delete it from local cache.
1751 if gem == gemPortID {
1752 onugem.GemPorts = append(onugem.GemPorts[:j], onugem.GemPorts[j+1:]...)
1753 f.onuGemInfoLock.Lock()
1754 f.onuGemInfoMap[onuID] = onugem
1755 f.onuGemInfoLock.Unlock()
1756 logger.Infow(ctx, "removed-gemport-from-local-cache",
1757 log.Fields{
1758 "intf-id": intfID,
1759 "onu-id": onuID,
1760 "deletedgemport-id": gemPortID,
1761 "gemports": onugem.GemPorts,
1762 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001763 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301764 }
1765 }
1766}
1767
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301768//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001769// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001770func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Girish Gowdra82c80982021-03-26 16:22:02 -07001771 gemPortID int32, flowID uint64, portNum uint32, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001772
Girish Gowdraa482f272021-03-24 23:04:19 -07001773 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
1774 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001775 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1776 log.Fields{
1777 "tpPath": tpPath,
1778 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001779
1780 used := f.isGemPortUsedByAnotherFlow(uint32(gemPortID))
1781
1782 if used {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001783 f.gemToFlowIDsKey.RLock()
1784 flowIDs := f.gemToFlowIDs[uint32(gemPortID)]
1785 f.gemToFlowIDsKey.RUnlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001786
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001787 for i, flowIDinMap := range flowIDs {
1788 if flowIDinMap == flowID {
1789 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001790 f.gemToFlowIDsKey.Lock()
1791 f.gemToFlowIDs[uint32(gemPortID)] = flowIDs
1792 f.gemToFlowIDsKey.Unlock()
1793 // everytime gemToFlowIDs cache is updated the same should be updated
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001794 // in kv store by calling UpdateFlowIDsForGem
Girish Gowdraa482f272021-03-24 23:04:19 -07001795 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, intfID, uint32(gemPortID), flowIDs); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001796 return err
1797 }
1798 break
1799 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001800 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001801 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1802 log.Fields{
1803 "gemport-id": gemPortID,
1804 "usedByFlows": flowIDs,
1805 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -07001806
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001807 return nil
1808 }
1809 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 -07001810 f.deleteGemPortFromLocalCache(ctx, intfID, uint32(onuID), uint32(gemPortID))
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001811 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, intfID, uint32(onuID), uint32(gemPortID)) // ignore error and proceed.
1812 //everytime an entry is deleted from gemToFlowIDs cache, the same should be updated in kv as well
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001813 // by calling DeleteFlowIDsForGem
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001814 f.gemToFlowIDsKey.Lock()
1815 delete(f.gemToFlowIDs, uint32(gemPortID))
1816 f.gemToFlowIDsKey.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001817
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001818 f.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, uint32(gemPortID))
1819
1820 f.resourceMgr.FreeGemPortID(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001821
1822 // Delete the gem port on the ONU.
Girish Gowdraa482f272021-03-24 23:04:19 -07001823 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001824 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
1825 log.Fields{
1826 "err": err,
Girish Gowdraa482f272021-03-24 23:04:19 -07001827 "intfID": intfID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001828 "onu-id": onuID,
1829 "uni-id": uniID,
1830 "device-id": f.deviceHandler.device.Id,
1831 "gemport-id": gemPortID})
1832 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001833 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1834 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1835 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1836 log.Fields{
1837 "tp-id": tpID,
1838 "path": tpPath}, err)
1839 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001840 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001841 case *tp_pb.TechProfileInstance:
Gamze Abakacb0e6772021-06-10 08:32:12 +00001842 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst, uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001843 if !ok {
Girish Gowdraa482f272021-03-24 23:04:19 -07001844 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); 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.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001848 logger.Warn(ctx, err)
1849 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001850 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 -07001851 logger.Warn(ctx, err)
1852 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001853 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 -07001854 logger.Warn(ctx, err)
1855 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001856 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001857 case *tp_pb.EponTechProfileInstance:
Girish Gowdraa482f272021-03-24 23:04:19 -07001858 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001859 logger.Warn(ctx, err)
1860 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001861 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001862 logger.Warn(ctx, err)
1863 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001864 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001865 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001866 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001867 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05301868 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07001869 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05301870 "onu-id": onuID,
1871 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001872 "device-id": f.deviceHandler.device.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001873 "alloc-id": techprofileInst.AllocId})
Gamze Abakafee36392019-10-03 11:17:24 +00001874 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001875 default:
1876 logger.Errorw(ctx, "error-unknown-tech",
1877 log.Fields{
1878 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001879 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001880
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301881 return nil
1882}
1883
David K. Bainbridge794735f2020-02-11 21:01:37 -08001884// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07001885func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001886 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05301887 log.Fields{
1888 "flowDirection": flowDirection,
1889 "flow": *flow,
1890 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001891
1892 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001893 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00001894 }
1895
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301896 classifierInfo := make(map[string]interface{})
1897
Neha Sharma96b7bf22020-06-15 10:37:32 +00001898 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301899 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001900 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001901 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301902 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301903
David K. Bainbridge794735f2020-02-11 21:01:37 -08001904 onuID := int32(onu)
1905 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001906 tpID, err := getTpIDFromFlow(ctx, flow)
1907 if err != nil {
1908 return olterrors.NewErrNotFound("tp-id",
1909 log.Fields{
1910 "flow": flow,
1911 "intf-id": Intf,
1912 "onu-id": onuID,
1913 "uni-id": uniID,
1914 "device-id": f.deviceHandler.device.Id}, err)
1915 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301916
1917 for _, field := range flows.GetOfbFields(flow) {
1918 if field.Type == flows.IP_PROTO {
1919 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00001920 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301921 }
1922 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001923 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05301924 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001925 "flow-id": flow.Id,
1926 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05301927 "onu-id": onuID,
1928 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301929
1930 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1931 onuID = -1
1932 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00001933 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
1934 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001935 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001936 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001937 log.Fields{
1938 "port-number": inPort,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001939 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001940 return err
David K. Bainbridge794735f2020-02-11 21:01:37 -08001941 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301942 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001943
1944 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
1945 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001946 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
1947 return err
1948 }
Girish Gowdra82c80982021-03-26 16:22:02 -07001949
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001950 f.flowIDToGemsLock.Lock()
1951 gems, ok := f.flowIDToGems[flow.Id]
1952 if !ok {
1953 logger.Errorw(ctx, "flow-id-to-gem-map-not-found", log.Fields{"flowID": flow.Id})
1954 f.flowIDToGemsLock.Unlock()
1955 return olterrors.NewErrNotFound("flow-id-to-gem-map-not-found", log.Fields{"flowID": flow.Id}, nil)
1956 }
1957 copyOfGems := make([]uint32, len(gems))
1958 _ = copy(copyOfGems, gems)
1959 // Delete the flow-id to gemport list entry from the map now the flow is deleted.
1960 delete(f.flowIDToGems, flow.Id)
1961 f.flowIDToGemsLock.Unlock()
1962
1963 logger.Debugw(ctx, "gems-to-be-cleared", log.Fields{"gems": copyOfGems})
1964 for _, gem := range copyOfGems {
1965 if err = f.clearResources(ctx, Intf, onuID, uniID, int32(gem), flow.Id, portNum, tpID); err != nil {
Girish Gowdra0aca4982021-01-04 12:44:27 -08001966 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001967 "flow-id": flow.Id,
1968 "device-id": f.deviceHandler.device.Id,
1969 "onu-id": onuID,
1970 "intf": Intf,
1971 "gem": gem,
1972 "err": err,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001973 })
1974 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301975 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301976 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001977
Girish Gowdra82c80982021-03-26 16:22:02 -07001978 // Decrement reference count for the meter associated with the given <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
1979 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, Intf, uint32(onuID), uint32(uniID), tpID, false); err != nil {
1980 return err
1981 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001982 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001983}
1984
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001985//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07001986func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001987
Matteo Scandolof16389e2021-05-18 00:47:08 +00001988 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301989 var direction string
1990 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001991
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301992 for _, action := range flows.GetActions(flow) {
1993 if action.Type == flows.OUTPUT {
1994 if out := action.GetOutput(); out != nil {
1995 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00001996 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301997 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001998 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07001999 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002000 }
2001 }
2002 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002003
2004 if flows.HasGroup(flow) {
2005 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002006 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Esin Karamanccb714b2019-11-29 15:02:06 +00002007 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302008 direction = Upstream
2009 } else {
2010 direction = Downstream
2011 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302012
Girish Gowdracefae192020-03-19 18:14:10 -07002013 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002014 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002015
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002016 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002017}
2018
Esin Karamanae41e2b2019-12-17 18:13:13 +00002019//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2020func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2021 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2022 if ethType, ok := classifierInfo[EthType]; ok {
2023 if ethType.(uint32) == IPv4EthType {
2024 if ipProto, ok := classifierInfo[IPProto]; ok {
2025 if ipProto.(uint32) == IgmpProto {
2026 return true
2027 }
2028 }
2029 }
2030 }
2031 }
2032 return false
2033}
2034
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002035// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
2036func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *voltha.OfpFlowStats, addFlow bool, flowMetadata *voltha.FlowMetadata) error {
2037 // Step1 : Fill flowControlBlock
2038 // Step2 : Push the flowControlBlock to ONU channel
2039 // Step3 : Wait on response channel for response
2040 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002041 startTime := time.Now()
2042 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002043 errChan := make(chan error)
2044 flowCb := flowControlBlock{
2045 ctx: ctx,
2046 addFlow: addFlow,
2047 flow: flow,
2048 flowMetadata: flowMetadata,
2049 errChan: &errChan,
2050 }
2051 inPort, outPort := getPorts(flow)
2052 var onuID uint32
2053 if inPort != InvalidPort && outPort != InvalidPort {
2054 _, _, onuID, _ = ExtractAccessFromFlow(inPort, outPort)
2055 }
2056 // inPort or outPort is InvalidPort for trap-from-nni flows.
2057 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2058 // Send the flowCb on the ONU flow channel
2059 f.incomingFlows[onuID] <- flowCb
2060 // Wait on the channel for flow handlers return value
2061 err := <-errChan
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002062 logger.Infow(ctx, "process-flow--received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002063 return err
2064}
2065
2066// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2067// Each incoming flow is processed in a synchronous manner, i.e., the flow is processed to completion before picking another
2068func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(subscriberFlowChannel chan flowControlBlock) {
2069 for {
2070 // block on the channel to receive an incoming flow
2071 // process the flow completely before proceeding to handle the next flow
2072 flowCb := <-subscriberFlowChannel
2073 if flowCb.addFlow {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002074 logger.Info(flowCb.ctx, "adding-flow-start")
2075 startTime := time.Now()
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002076 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002077 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002078 // Pass the return value over the return channel
2079 *flowCb.errChan <- err
2080 } else {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002081 logger.Info(flowCb.ctx, "removing-flow-start")
2082 startTime := time.Now()
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002083 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002084 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002085 // Pass the return value over the return channel
2086 *flowCb.errChan <- err
2087 }
2088 }
2089}
2090
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002091// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302092// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002093func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002094 classifierInfo := make(map[string]interface{})
2095 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002096 var UsMeterID uint32
2097 var DsMeterID uint32
2098
Neha Sharma96b7bf22020-06-15 10:37:32 +00002099 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302100 log.Fields{
2101 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002102 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002103 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002104
Neha Sharma96b7bf22020-06-15 10:37:32 +00002105 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002106 if err != nil {
2107 // Error logging is already done in the called function
2108 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002109 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302110 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002111
Esin Karamanccb714b2019-11-29 15:02:06 +00002112 if flows.HasGroup(flow) {
2113 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002114 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002115 }
2116
manikkaraj k17652a72019-05-06 09:06:36 -04002117 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002118 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002119 if err != nil {
2120 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002121 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002122 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002123
Neha Sharma96b7bf22020-06-15 10:37:32 +00002124 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302125 log.Fields{
2126 "classifierinfo_inport": classifierInfo[InPort],
2127 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002128 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002129
Humera Kouser94d7a842019-08-25 19:04:32 -04002130 if ethType, ok := classifierInfo[EthType]; ok {
2131 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002132 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002133 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002134 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002135 if ethType.(uint32) == PPPoEDEthType {
2136 if voltha.Port_ETHERNET_NNI == IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
2137 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2138 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2139 }
2140 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002141 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002142 if ipProto, ok := classifierInfo[IPProto]; ok {
2143 if ipProto.(uint32) == IPProtoDhcp {
2144 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302145 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002146 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002147 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002148 }
2149 }
2150 }
2151 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002152 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002153 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002154 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002155 }
A R Karthick1f85b802019-10-11 05:06:05 +00002156
npujarec5762e2020-01-01 14:08:48 +05302157 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002158 // also update flowmgr cache
2159 f.onuGemInfoLock.Lock()
2160 onugem, ok := f.onuGemInfoMap[onuID]
2161 if ok {
2162 found := false
2163 for _, uni := range onugem.UniPorts {
2164 if uni == portNo {
2165 found = true
2166 break
2167 }
2168 }
2169 if !found {
2170 onugem.UniPorts = append(onugem.UniPorts, portNo)
2171 f.onuGemInfoMap[onuID] = onugem
2172 logger.Infow(ctx, "added uni port to onugem cache", log.Fields{"uni": portNo})
2173 }
2174 }
2175 f.onuGemInfoLock.Unlock()
A R Karthick1f85b802019-10-11 05:06:05 +00002176
Neha Sharma96b7bf22020-06-15 10:37:32 +00002177 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002178 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302179 return olterrors.NewErrNotFound("tpid-for-flow",
2180 log.Fields{
2181 "flow": flow,
2182 "intf-id": IntfID,
2183 "onu-id": onuID,
2184 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002185 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002186 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302187 log.Fields{
2188 "tp-id": TpID,
2189 "intf-id": intfID,
2190 "onu-id": onuID,
2191 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002192 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002193 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002194 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002195 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002196 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002197 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002198
2199 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002200 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002201}
Girish Gowdra3d633032019-12-10 16:37:05 +05302202
Esin Karamanccb714b2019-11-29 15:02:06 +00002203// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002204func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002205 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002206 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302207 "classifier-info": classifierInfo,
2208 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002209
Esin Karaman65409d82020-03-18 10:58:18 +00002210 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002211 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002212 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002213 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002214
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002215 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002216
David K. Bainbridge794735f2020-02-11 21:01:37 -08002217 onuID := NoneOnuID
2218 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002219
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002220 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002221 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002222 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002223 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002224 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2225 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002226 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002227 }
2228 groupID := actionInfo[GroupID].(uint32)
2229 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002230 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002231 FlowType: Multicast,
2232 NetworkIntfId: int32(networkInterfaceID),
2233 GroupId: groupID,
2234 Classifier: classifierProto,
2235 Priority: int32(flow.Priority),
2236 Cookie: flow.Cookie}
2237
Kent Hagermane6ff1012020-07-14 15:07:53 -04002238 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002239 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002240 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002241 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002242 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002243 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002244 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002245 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002246 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002247 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002248 //cached group can be removed now
2249 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002250 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002251 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002252 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002253
David K. Bainbridge794735f2020-02-11 21:01:37 -08002254 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002255}
2256
Esin Karaman65409d82020-03-18 10:58:18 +00002257//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2258func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2259 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002260 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002261 if err != nil {
2262 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2263 }
2264 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002265 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002266
2267 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2268 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002269}
2270
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002271//sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002272func (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 -07002273
Neha Sharma96b7bf22020-06-15 10:37:32 +00002274 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302275 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002276 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302277 log.Fields{
2278 "intf-id": intfID,
2279 "onu-id": onuID,
2280 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002281 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302282 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002283 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002284
Neha Sharma96b7bf22020-06-15 10:37:32 +00002285 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002286 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{
2287 UniId: uniID,
2288 TpInstancePath: tpPath,
2289 TechTpInstance: &ic.InterAdapterTechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
2290 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002291 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002292 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
manikkaraj k17652a72019-05-06 09:06:36 -04002293 tpDownloadMsg,
2294 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03002295 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002296 onuDev.deviceType,
2297 onuDev.deviceID,
2298 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002299 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302300 return olterrors.NewErrCommunication("send-techprofile-download-request",
2301 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03002302 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05302303 "to-adapter": onuDev.deviceType,
2304 "onu-id": onuDev.deviceID,
2305 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002306 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002307 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302308 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302309}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002310
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302311//UpdateOnuInfo function adds onu info to cache and kvstore
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002312//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002313func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302314
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002315 f.onuGemInfoLock.RLock()
2316 _, ok := f.onuGemInfoMap[onuID]
2317 f.onuGemInfoLock.RUnlock()
Girish Gowdra9602eb42020-09-09 15:50:39 -07002318 // If the ONU already exists in onuGemInfo list, nothing to do
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002319 if ok {
2320 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2321 log.Fields{"onuID": onuID,
2322 "serialNum": serialNum})
2323 return nil
Girish Gowdra9602eb42020-09-09 15:50:39 -07002324 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002325
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002326 onuGemInfo := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2327 f.onuGemInfoLock.Lock()
2328 f.onuGemInfoMap[onuID] = &onuGemInfo
2329 f.onuGemInfoLock.Unlock()
2330 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onuID, onuGemInfo); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002331 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302332 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002333 logger.Infow(ctx, "updated-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302334 log.Fields{
2335 "intf-id": intfID,
2336 "onu-id": onuID,
2337 "serial-num": serialNum,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002338 "onu": onuGemInfo,
Shrey Baid26912972020-04-16 21:02:31 +05302339 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002340 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002341}
2342
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302343//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302344func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002345
Neha Sharma96b7bf22020-06-15 10:37:32 +00002346 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302347 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002348 "gem-port-id": gemPort,
2349 "intf-id": intfID,
2350 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002351 "device-id": f.deviceHandler.device.Id})
2352 f.onuGemInfoLock.RLock()
2353 onugem, ok := f.onuGemInfoMap[onuID]
2354 f.onuGemInfoLock.RUnlock()
2355 if !ok {
2356 logger.Warnw(ctx, "onu gem info is missing", log.Fields{
2357 "gem-port-id": gemPort,
2358 "intf-id": intfID,
2359 "onu-id": onuID,
2360 "device-id": f.deviceHandler.device.Id})
2361 return
2362 }
2363
2364 if onugem.OnuID == onuID {
2365 // check if gem already exists , else update the cache and kvstore
2366 for _, gem := range onugem.GemPorts {
2367 if gem == gemPort {
2368 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
2369 log.Fields{
2370 "gem": gemPort,
2371 "device-id": f.deviceHandler.device.Id})
2372 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302373 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302374 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002375 onugem.GemPorts = append(onugem.GemPorts, gemPort)
2376 f.onuGemInfoLock.Lock()
2377 f.onuGemInfoMap[onuID] = onugem
2378 f.onuGemInfoLock.Unlock()
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002379 logger.Debugw(ctx, "updated onu gem info from cache", log.Fields{"onugem": onugem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002380 } else {
2381 logger.Warnw(ctx, "mismatched onu id", log.Fields{
2382 "gem-port-id": gemPort,
2383 "intf-id": intfID,
2384 "onu-id": onuID,
2385 "device-id": f.deviceHandler.device.Id})
2386 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302387 }
npujarec5762e2020-01-01 14:08:48 +05302388 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302389 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002390 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302391 log.Fields{
2392 "intf-id": intfID,
2393 "onu-id": onuID,
2394 "gemPort": gemPort,
2395 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002396 return
2397 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002398 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302399 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002400 "gem-port-id": gemPort,
2401 "intf-id": intfID,
2402 "onu-id": onuID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002403 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002404}
2405
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002406//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302407func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002408 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002409
2410 if packetIn.IntfType == "pon" {
2411 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002412 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002413 onuID, uniID := packetIn.OnuId, packetIn.UniId
2414 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 +00002415
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002416 if packetIn.PortNo != 0 {
2417 logicalPortNum = packetIn.PortNo
2418 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002419 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002420 }
2421 // 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 +00002422 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002423 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002424 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002425 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002426
2427 if logger.V(log.DebugLevel) {
2428 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2429 log.Fields{
2430 "logical-port-num": logicalPortNum,
2431 "intf-type": packetIn.IntfType,
2432 "packet": hex.EncodeToString(packetIn.Pkt),
2433 })
2434 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002435 return logicalPortNum, nil
2436}
2437
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002438//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002439func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002440 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002441
2442 ctag, priority, err := getCTagFromPacket(ctx, packet)
2443 if err != nil {
2444 return 0, err
2445 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302446
Esin Karaman7fb80c22020-07-16 14:23:33 +00002447 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002448 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002449 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002450 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002451 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302452 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002453 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302454 log.Fields{
2455 "pktinkey": pktInkey,
2456 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002457
2458 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002459 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302460 //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 +00002461 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302462 if err == nil {
2463 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002464 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302465 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002466 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002467 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302468 log.Fields{
2469 "pktinkey": pktInkey,
2470 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302471 return gemPortID, nil
2472 }
2473 }
Shrey Baid26912972020-04-16 21:02:31 +05302474 return uint32(0), olterrors.NewErrNotFound("gem-port",
2475 log.Fields{
2476 "pktinkey": pktInkey,
2477 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002478
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002479}
2480
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002481func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2482 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002483 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002484 classifier[PacketTagType] = DoubleTag
2485 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002486 /* We manage flowId resource pool on per PON port basis.
2487 Since this situation is tricky, as a hack, we pass the NNI port
2488 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002489 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002490 on NNI port, use onu_id as -1 (invalid)
2491 ****************** CAVEAT *******************
2492 This logic works if the NNI Port Id falls within the same valid
2493 range of PON Port Ids. If this doesn't work for some OLT Vendor
2494 we need to have a re-look at this.
2495 *********************************************
2496 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002497 onuID := -1
2498 uniID := -1
2499 gemPortID := -1
2500 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002501 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302502 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302503 return olterrors.NewErrNotFound("nni-intreface-id",
2504 log.Fields{
2505 "classifier": classifier,
2506 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002507 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302508 }
2509
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002510 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002511 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002512 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002513 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002514
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002515 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2516 log.Fields{
2517 "classifier": classifier,
2518 "action": action,
2519 "flowId": logicalFlow.Id,
2520 "intf-id": networkInterfaceID})
2521
David K. Bainbridge794735f2020-02-11 21:01:37 -08002522 classifierProto, err := makeOpenOltClassifierField(classifier)
2523 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002524 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002525 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002526 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002527 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002528 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002529 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002530 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002531 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002532 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2533 OnuId: int32(onuID), // OnuId not required
2534 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002535 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002536 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002537 AllocId: int32(allocID), // AllocId not used
2538 NetworkIntfId: int32(networkInterfaceID),
2539 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002540 Classifier: classifierProto,
2541 Action: actionProto,
2542 Priority: int32(logicalFlow.Priority),
2543 Cookie: logicalFlow.Cookie,
2544 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002545 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002546 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002547 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002548 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002549 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002550}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002551
Esin Karamanae41e2b2019-12-17 18:13:13 +00002552//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2553func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2554 var packetType string
2555 ovid, ivid := false, false
2556 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2557 vid := vlanID & VlanvIDMask
2558 if vid != ReservedVlan {
2559 ovid = true
2560 }
2561 }
2562 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2563 vid := uint32(metadata)
2564 if vid != ReservedVlan {
2565 ivid = true
2566 }
2567 }
2568 if ovid && ivid {
2569 packetType = DoubleTag
2570 } else if !ovid && !ivid {
2571 packetType = Untagged
2572 } else {
2573 packetType = SingleTag
2574 }
2575 return packetType
2576}
2577
2578//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002579func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002580 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002581 action := make(map[string]interface{})
2582 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2583 action[TrapToHost] = true
2584 /* We manage flowId resource pool on per PON port basis.
2585 Since this situation is tricky, as a hack, we pass the NNI port
2586 index (network_intf_id) as PON port Index for the flowId resource
2587 pool. Also, there is no ONU Id available for trapping packets
2588 on NNI port, use onu_id as -1 (invalid)
2589 ****************** CAVEAT *******************
2590 This logic works if the NNI Port Id falls within the same valid
2591 range of PON Port Ids. If this doesn't work for some OLT Vendor
2592 we need to have a re-look at this.
2593 *********************************************
2594 */
2595 onuID := -1
2596 uniID := -1
2597 gemPortID := -1
2598 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002599 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002600 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302601 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002602 "classifier": classifier,
2603 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002604 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002605 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002606 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002607 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002608 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002609 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002610
David K. Bainbridge794735f2020-02-11 21:01:37 -08002611 classifierProto, err := makeOpenOltClassifierField(classifier)
2612 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002613 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002614 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002615 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002616 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002617 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002618 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002619 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002620 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002621 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2622 OnuId: int32(onuID), // OnuId not required
2623 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002624 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002625 FlowType: Downstream,
2626 AllocId: int32(allocID), // AllocId not used
2627 NetworkIntfId: int32(networkInterfaceID),
2628 GemportId: int32(gemPortID), // GemportId not used
2629 Classifier: classifierProto,
2630 Action: actionProto,
2631 Priority: int32(logicalFlow.Priority),
2632 Cookie: logicalFlow.Cookie,
2633 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002634 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002635 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002636 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002637 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002638
David K. Bainbridge794735f2020-02-11 21:01:37 -08002639 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002640}
2641
salmansiddiqui7ac62132019-08-22 03:58:50 +00002642func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2643 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302644 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002645 }
2646 if Dir == tp_pb.Direction_UPSTREAM {
2647 return "upstream", nil
2648 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2649 return "downstream", nil
2650 }
2651 return "", nil
2652}
2653
Kent Hagermane6ff1012020-07-14 15:07:53 -04002654// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302655func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002656 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002657 tpID uint32, uni string) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002658 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002659 intfID := args[IntfID]
2660 onuID := args[OnuID]
2661 uniID := args[UniID]
2662 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002663 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002664 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002665 gemToAes := make(map[uint32]bool)
2666
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002667 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002668 var direction = tp_pb.Direction_UPSTREAM
2669 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002670 case *tp_pb.TechProfileInstance:
Gamze Abaka7650be62021-02-26 10:50:36 +00002671 if IsUpstream(actionInfo[Output].(uint32)) {
2672 attributes = TpInst.UpstreamGemPortAttributeList
2673 } else {
2674 attributes = TpInst.DownstreamGemPortAttributeList
2675 direction = tp_pb.Direction_DOWNSTREAM
2676 }
2677 default:
2678 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
2679 return
2680 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002681
2682 if len(gemPorts) == 1 {
2683 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002684 gemPortID = gemPorts[0]
2685 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002686 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2687 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002688 pBitMap := attributes[idx].PbitMap
2689 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2690 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2691 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
2692 // this pcp bit traffic.
2693 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2694 if pbitSet == pbit1 {
2695 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2696 pbitToGem[pcp] = gemID
2697 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002698 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002699 }
2700 }
2701 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002702 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2703 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2704 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002705 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002706 }
2707
Gamze Abaka7650be62021-02-26 10:50:36 +00002708 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2709 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2710
salmansiddiqui7ac62132019-08-22 03:58:50 +00002711 if ipProto, ok := classifierInfo[IPProto]; ok {
2712 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002713 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002714 "tp-id": tpID,
2715 "alloc-id": allocID,
2716 "intf-id": intfID,
2717 "onu-id": onuID,
2718 "uni-id": uniID,
2719 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002720 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002721 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002722 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002723 }
2724
Girish Gowdra32625212020-04-29 11:26:35 -07002725 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002726 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302727 log.Fields{
2728 "intf-id": intfID,
2729 "onu-id": onuID,
2730 "uni-id": uniID,
2731 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002732 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002733 logger.Warn(ctx, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002734 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002735 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002736 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002737 return
2738 }
2739 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002740 if ethType.(uint32) == EapEthType {
2741 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002742 "intf-id": intfID,
2743 "onu-id": onuID,
2744 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002745 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002746 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002747 var vlanID uint32
2748 if val, ok := classifierInfo[VlanVid]; ok {
2749 vlanID = (val.(uint32)) & VlanvIDMask
2750 } else {
2751 vlanID = DefaultMgmtVlan
2752 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002753 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002754 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002755 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002756 } else if ethType.(uint32) == PPPoEDEthType {
2757 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2758 "tp-id": tpID,
2759 "alloc-id": allocID,
2760 "intf-id": intfID,
2761 "onu-id": onuID,
2762 "uni-id": uniID,
2763 })
2764 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002765 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002766 logger.Warn(ctx, err)
2767 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002768 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002769 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002770 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002771 "intf-id": intfID,
2772 "onu-id": onuID,
2773 "uni-id": uniID,
2774 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002775 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002776 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002777 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002778 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002779 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002780 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002781 "intf-id": intfID,
2782 "onu-id": onuID,
2783 "uni-id": uniID,
2784 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002785 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002786 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002787 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002788 }
2789 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002790 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05302791 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002792 "intf-id": intfID,
2793 "onu-id": onuID,
2794 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05302795 "classifier": classifierInfo,
2796 "action": actionInfo,
2797 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002798 return
2799 }
2800 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002801 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002802 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002803 logger.Warn(ctx, err)
2804 }
2805 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002806}
2807
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002808func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002809 f.gemToFlowIDsKey.RLock()
2810 flowIDList := f.gemToFlowIDs[gemPortID]
2811 f.gemToFlowIDsKey.RUnlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002812 return len(flowIDList) > 1
2813
Gamze Abakafee36392019-10-03 11:17:24 +00002814}
2815
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002816func (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 +05302817 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002818 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2819 for _, currentGemPort := range currentGemPorts {
2820 for _, tpGemPort := range tpGemPorts {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002821 if (currentGemPort == tpGemPort.GemportId) && (currentGemPort != gemPortID) {
Gamze Abakafee36392019-10-03 11:17:24 +00002822 return true, currentGemPort
2823 }
2824 }
2825 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00002826 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
2827 return false, 0
2828}
Girish Gowdra54934262019-11-13 14:19:55 +05302829
Gamze Abakacb0e6772021-06-10 08:32:12 +00002830func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002831 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
2832 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
2833 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 +00002834 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05302835 for i := 0; i < len(tpInstances); i++ {
2836 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00002837 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002838 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Gamze Abakacb0e6772021-06-10 08:32:12 +00002839 logger.Debugw(ctx, "alloc-is-in-use",
2840 log.Fields{
2841 "device-id": f.deviceHandler.device.Id,
2842 "intfID": sq.intfID,
2843 "onuID": sq.onuID,
2844 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002845 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00002846 })
2847 return true
Girish Gowdra54934262019-11-13 14:19:55 +05302848 }
2849 }
2850 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00002851 return false
Gamze Abakafee36392019-10-03 11:17:24 +00002852}
2853
Neha Sharma96b7bf22020-06-15 10:37:32 +00002854func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002855 for _, field := range flows.GetOfbFields(flow) {
2856 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002857 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002858 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002859 } else if field.Type == flows.ETH_DST {
2860 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002861 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07002862 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002863 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002864 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002865 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002866 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002867 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002868 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05302869 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00002870 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002871 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002872 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002873 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002874 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002875 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002876 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002877 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002878 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002879 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002880 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002881 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002882 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002883 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002884 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002885 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002886 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002887 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002888 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07002889 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002890 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002891 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002892 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002893 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002894 return
2895 }
2896 }
2897}
2898
Neha Sharma96b7bf22020-06-15 10:37:32 +00002899func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07002900 for _, action := range flows.GetActions(flow) {
2901 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002902 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002903 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002904 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002905 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002906 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002907 }
Scott Baker355d1742019-10-24 10:57:52 -07002908 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002909 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00002910 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002911 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002912 if out := action.GetPush(); out != nil {
2913 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002914 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002915 } else {
2916 actionInfo[PushVlan] = true
2917 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00002918 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05302919 log.Fields{
2920 "push-tpid": actionInfo[TPID].(uint32),
2921 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002922 }
2923 }
Scott Baker355d1742019-10-24 10:57:52 -07002924 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002925 if out := action.GetSetField(); out != nil {
2926 if field := out.GetField(); field != nil {
2927 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00002928 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002929 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002930 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
2931 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002932 }
2933 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002934 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002935 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002936 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002937 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002938 }
2939 }
2940 return nil
2941}
2942
Neha Sharma96b7bf22020-06-15 10:37:32 +00002943func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00002944 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00002945 fieldtype := ofbField.GetType()
2946 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00002947 if vlan := ofbField.GetVlanVid(); vlan != 0 {
2948 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00002949 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002950 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002951 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00002952 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00002953 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
2954 pcp := ofbField.GetVlanPcp()
2955 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002956 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002957 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002958 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00002959 }
2960 }
2961}
2962
Neha Sharma96b7bf22020-06-15 10:37:32 +00002963func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00002964 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002965 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00002966 } else {
2967 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00002968 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002969 }
2970}
2971
Neha Sharma96b7bf22020-06-15 10:37:32 +00002972func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002973 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002974 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002975 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2976 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002977 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002978 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00002979 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05302980 log.Fields{
2981 "newinport": classifierInfo[InPort].(uint32),
2982 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002983 } else {
Shrey Baid26912972020-04-16 21:02:31 +05302984 return olterrors.NewErrNotFound("child-in-port",
2985 log.Fields{
2986 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
2987 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002988 }
2989 }
2990 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002991 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00002992 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07002993 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07002994 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002995 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00002996 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05302997 log.Fields{
2998 "newoutport": actionInfo[Output].(uint32),
2999 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003000 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303001 return olterrors.NewErrNotFound("out-port",
3002 log.Fields{
3003 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3004 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003005 }
3006 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3007 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003008 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003009 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003010 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303011 log.Fields{
3012 "newinport": actionInfo[Output].(uint32),
3013 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003014 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303015 return olterrors.NewErrNotFound("nni-port",
3016 log.Fields{
3017 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3018 "in-port": classifierInfo[InPort].(uint32),
3019 "out-port": actionInfo[Output].(uint32),
3020 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003021 }
3022 }
3023 }
3024 return nil
3025}
Gamze Abakafee36392019-10-03 11:17:24 +00003026
Neha Sharma96b7bf22020-06-15 10:37:32 +00003027func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003028 /* Metadata 8 bytes:
3029 Most Significant 2 Bytes = Inner VLAN
3030 Next 2 Bytes = Tech Profile ID(TPID)
3031 Least Significant 4 Bytes = Port ID
3032 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3033 subscriber related flows.
3034 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003035 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003036 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003037 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003038 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003039 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003040 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003041}
3042
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003043func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3044 for _, sliceElement := range slice {
3045 if sliceElement == item {
3046 return slice
3047 }
3048 }
3049 return append(slice, item)
3050}
3051
3052func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003053 for _, sliceElement := range slice {
3054 if sliceElement == item {
3055 return slice
3056 }
3057 }
3058 return append(slice, item)
3059}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303060
3061// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003062func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303063
3064 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3065 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003066 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003067 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003068 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003069 log.Fields{
3070 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003071 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003072 return uint32(0), err
3073 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003074 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303075 return intfID, nil
3076 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003077 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003078 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003079 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003080 log.Fields{
3081 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003082 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003083 return uint32(0), err
3084 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003085 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303086 return intfID, nil
3087 }
3088 return uint32(0), nil
3089}
3090
3091// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003092func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3093 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3094 if err != nil {
3095 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3096 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3097 return
3098 }
3099 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003100
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003101 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003102 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003103 f.packetInGemPortLock.RUnlock()
3104
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303105 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003106 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003107 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 +05303108 log.Fields{
3109 "pktinkey": pktInkey,
3110 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003111 return
3112 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303113 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003114 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003115 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003116 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003117
npujarec5762e2020-01-01 14:08:48 +05303118 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003119 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 +05303120 log.Fields{
3121 "pktinkey": pktInkey,
3122 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303123}
3124
Esin Karaman7fb80c22020-07-16 14:23:33 +00003125//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3126func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3127 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003128 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003129 return 0, 0, errors.New("invalid packet length")
3130 }
3131 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3132 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3133
3134 var index int8
3135 if outerEthType == 0x8100 {
3136 if innerEthType == 0x8100 {
3137 // q-in-q 802.1ad or 802.1q double tagged packet.
3138 // get the inner vlanId
3139 index = 18
3140 } else {
3141 index = 14
3142 }
3143 priority := (packet[index] >> 5) & 0x7
3144 //13 bits composes vlanId value
3145 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3146 return vlan, priority, nil
3147 }
3148 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3149 return 0, 0, nil
3150}
3151
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003152func (f *OpenOltFlowMgr) loadFlowIDsForGemAndGemIDsForFlow(ctx context.Context) {
3153 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - start")
3154 f.onuGemInfoLock.RLock()
3155 f.gemToFlowIDsKey.Lock()
3156 f.flowIDToGemsLock.Lock()
3157 for _, og := range f.onuGemInfoMap {
3158 for _, gem := range og.GemPorts {
3159 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, f.ponPortIdx, gem)
3160 if err != nil {
3161 f.gemToFlowIDs[gem] = flowIDs
3162 for _, flowID := range flowIDs {
3163 if _, ok := f.flowIDToGems[flowID]; !ok {
3164 f.flowIDToGems[flowID] = []uint32{gem}
3165 } else {
3166 f.flowIDToGems[flowID] = appendUnique32bit(f.flowIDToGems[flowID], gem)
3167 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303168 }
3169 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303170 }
3171 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003172 f.flowIDToGemsLock.Unlock()
3173 f.gemToFlowIDsKey.Unlock()
3174 f.onuGemInfoLock.RUnlock()
3175 logger.Debug(ctx, "loadFlowIDsForGemAndGemIDsForFlow - end")
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303176}
Esin Karamanccb714b2019-11-29 15:02:06 +00003177
Girish Gowdra9602eb42020-09-09 15:50:39 -07003178//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3179// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003180func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003181 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003182 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3183 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003184 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003185 "flow-id": flow.Id,
3186 "device-id": f.deviceHandler.device.Id})
3187 // Remove from device
3188 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3189 // DKB
3190 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3191 log.Fields{
3192 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003193 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003194 return err
3195 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003196
3197 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003198}
3199
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003200func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, ponID uint32, onuID uint32, uniID uint32) *ic.InterAdapterTechProfileDownloadMessage {
3201 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003202 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003203 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
3204 return nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003205 }
3206
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003207 switch tpInst := tpInst.(type) {
3208 case *tp_pb.TechProfileInstance:
3209 logger.Debugw(ctx, "fetched-tp-instance-successfully--formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
3210 return &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID,
3211 TpInstancePath: tpPath,
3212 TechTpInstance: &ic.InterAdapterTechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003213 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003214 case *openoltpb2.EponTechProfileInstance:
3215 return &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID,
3216 TpInstancePath: tpPath,
3217 TechTpInstance: &ic.InterAdapterTechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
3218 }
3219 default:
3220 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003221 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003222 return nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003223}
3224
Girish Gowdrabcf98af2021-07-01 08:24:42 -07003225func (f *OpenOltFlowMgr) getOnuGemInfoList(ctx context.Context) []rsrcMgr.OnuGemInfo {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003226 var onuGemInfoLst []rsrcMgr.OnuGemInfo
3227 f.onuGemInfoLock.RLock()
3228 defer f.onuGemInfoLock.RUnlock()
3229 for _, v := range f.onuGemInfoMap {
3230 onuGemInfoLst = append(onuGemInfoLst, *v)
3231 }
3232 return onuGemInfoLst
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003233}