blob: e3d60d9dc3de28419247d0dba2b1f4fba362bcd5 [file] [log] [blame]
Abhilash S.L7f17e402019-03-15 17:40:41 +05301/*
Joey Armstrongf9bffdf2022-12-27 07:05:28 -05002 * Copyright 2019-2023 Open Networking Foundation (ONF) and the ONF Contributors
Abhilash S.L7f17e402019-03-15 17:40:41 +05303
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
Joey Armstrong3f0e2422023-07-05 18:25:41 -040017// Package resourcemanager provides the utility for managing resources
manikkaraj kbf256be2019-03-25 00:13:48 +053018package resourcemanager
Abhilash S.L7f17e402019-03-15 17:40:41 +053019
20import (
npujarec5762e2020-01-01 14:08:48 +053021 "context"
Girish Gowdru0c588b22019-04-23 23:24:56 -040022 "encoding/json"
23 "errors"
24 "fmt"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070025 "strings"
Girish Gowdra38d533d2020-03-30 20:38:51 -070026 "sync"
Neha Sharmacc656962020-04-14 14:26:11 +000027 "time"
Abhilash S.L7f17e402019-03-15 17:40:41 +053028
khenaidoo106c61a2021-08-11 18:05:46 -040029 tp "github.com/opencord/voltha-lib-go/v7/pkg/techprofile"
30
31 "github.com/opencord/voltha-lib-go/v7/pkg/db"
32 "github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
33 "github.com/opencord/voltha-lib-go/v7/pkg/log"
34 ponrmgr "github.com/opencord/voltha-lib-go/v7/pkg/ponresourcemanager"
35 ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
36 "github.com/opencord/voltha-protos/v5/go/openolt"
Abhilash S.L7f17e402019-03-15 17:40:41 +053037)
38
salmansiddiqui7ac62132019-08-22 03:58:50 +000039const (
40 // KvstoreTimeout specifies the time out for KV Store Connection
Neha Sharmacc656962020-04-14 14:26:11 +000041 KvstoreTimeout = 5 * time.Second
Matteo Scandolodfa7a972020-11-06 13:03:40 -080042 // BasePathKvStore - <pathPrefix>/openolt/<device_id>
43 BasePathKvStore = "%s/openolt/{%s}"
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070044 // tpIDPathSuffix - <(pon_id, onu_id, uni_id)>/tp_id
45 tpIDPathSuffix = "{%d,%d,%d}/tp_id"
Gamze Abakafee36392019-10-03 11:17:24 +000046 //MeterIDPathSuffix - <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
47 MeterIDPathSuffix = "{%d,%d,%d}/{%d}/meter_id/{%s}"
Girish Gowdra950326e2021-11-05 12:43:24 -070048
49 // OnuPacketInPathPrefix - path prefix where ONU packet-in vlanID/PCP is stored
Girish Gowdraa09aeab2020-09-14 16:30:52 -070050 //format: onu_packetin/{<intfid>,<onuid>,<logicalport>}
Girish Gowdra950326e2021-11-05 12:43:24 -070051 OnuPacketInPathPrefix = "onu_packetin/{%d,%d,%d}"
52 // OnuPacketInPath path on the kvstore to store packetin gemport,which will be used for packetin, packetout
Girish Gowdraa09aeab2020-09-14 16:30:52 -070053 //format: onu_packetin/{<intfid>,<onuid>,<logicalport>}/{<vlanId>,<priority>}
Girish Gowdra950326e2021-11-05 12:43:24 -070054 OnuPacketInPath = OnuPacketInPathPrefix + "/{%d,%d}"
55
56 //FlowIDsForGemPathPrefix format: flowids_for_gem/<intfid>
57 FlowIDsForGemPathPrefix = "flowids_per_gem/{%d}"
58 //FlowIDsForGem flowids_for_gem/<intfid>/<gemport-id>
59 FlowIDsForGem = FlowIDsForGemPathPrefix + "/{%d}"
60
Esin Karamanccb714b2019-11-29 15:02:06 +000061 //McastQueuesForIntf multicast queues for pon interfaces
62 McastQueuesForIntf = "mcast_qs_for_int"
63 //FlowGroup flow_groups/<flow_group_id>
64 // A group is stored under this path on the KV store after it has been installed to the device.
65 // It should also be deleted after it has been removed from the device accordingly.
66 FlowGroup = "flow_groups/{%d}"
67 //FlowGroupCached flow_groups_cached/<flow_group_id>
68 // When a group add request received, we create the group without setting any members to it since we cannot
69 // set any members to a group until it is associated with a multicast flow. It is a BAL limitation.
70 // When the related multicast flow has been created we perform set members operation for the group.
71 // That is why we need to keep the members of a group until the multicast flow creation request comes.
72 // We preserve the groups under "FlowGroupsCached" directory in the KV store temporarily. Having set members,
73 // we remove the group from the cached group store.
74 FlowGroupCached = "flow_groups_cached/{%d}"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070075
76 //FlowIDPath - Path on the KV store for storing list of Flow IDs for a given subscriber
77 //Format: BasePathKvStore/<(pon_intf_id, onu_id, uni_id)>/flow_ids
78 FlowIDPath = "{%s}/flow_ids"
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070079
Girish Gowdra950326e2021-11-05 12:43:24 -070080 //OnuGemInfoPathPathPrefix format: onu_gem_info/<intfid>
81 OnuGemInfoPathPathPrefix = "onu_gem_info/{%d}"
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070082 //OnuGemInfoPath is path on the kvstore to store onugem info map
Girish Gowdra950326e2021-11-05 12:43:24 -070083 //format: onu_gem_info/<intfid>/<onu_id>
84 OnuGemInfoPath = OnuGemInfoPathPathPrefix + "/{%d}"
yasin saplid0566272021-12-21 09:10:30 +000085
86 // NNI uint32 version of -1 which represents the NNI port
87 NNI = 4294967295
salmansiddiqui7ac62132019-08-22 03:58:50 +000088)
Abhilash S.L7f17e402019-03-15 17:40:41 +053089
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070090// FlowInfo holds the flow information
Abhilash S.L8ee90712019-04-29 16:24:22 +053091type FlowInfo struct {
Girish Gowdraa09aeab2020-09-14 16:30:52 -070092 Flow *openolt.Flow
93 IsSymmtricFlow bool
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +053094}
95
96// OnuGemInfo holds onu information along with gem port list and uni port list
97type OnuGemInfo struct {
98 OnuID uint32
99 SerialNumber string
100 IntfID uint32
101 GemPorts []uint32
102 UniPorts []uint32
103}
104
105// PacketInInfoKey is the key for packet in gemport
106type PacketInInfoKey struct {
107 IntfID uint32
108 OnuID uint32
109 LogicalPort uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +0000110 VlanID uint16
111 Priority uint8
Abhilash S.L8ee90712019-04-29 16:24:22 +0530112}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700113
Esin Karamanccb714b2019-11-29 15:02:06 +0000114// GroupInfo holds group information
115type GroupInfo struct {
116 GroupID uint32
117 OutPorts []uint32
118}
119
Girish Gowdraa482f272021-03-24 23:04:19 -0700120// MeterInfo store meter information at path <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
121type MeterInfo struct {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700122 RefCnt uint8 // number of flow references for this meter. When RefCnt is 0, the MeterInfo should be deleted.
123 MeterID uint32
Girish Gowdraa482f272021-03-24 23:04:19 -0700124}
125
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700126// OpenOltResourceMgr holds resource related information as provided below for each field
Abhilash S.L7f17e402019-03-15 17:40:41 +0530127type OpenOltResourceMgr struct {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700128 PonIntfID uint32
Neha Sharma3f221ae2020-04-29 19:02:12 +0000129 DeviceID string // OLT device id
130 Address string // Host and port of the kv store to connect to
131 Args string // args
132 KVStore *db.Backend // backend kv store connection handle
133 DeviceType string
134 DevInfo *openolt.DeviceInfo // device information
Girish Gowdru0c588b22019-04-23 23:24:56 -0400135 // array of pon resource managers per interface technology
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700136 PonRsrMgr *ponrmgr.PONResourceManager
Girish Gowdra38d533d2020-03-30 20:38:51 -0700137
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700138 // Local maps used for write-through-cache - start
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700139 allocIDsForOnu map[string][]uint32
140 allocIDsForOnuLock sync.RWMutex
141
142 gemPortIDsForOnu map[string][]uint32
143 gemPortIDsForOnuLock sync.RWMutex
144
145 techProfileIDsForOnu map[string][]uint32
146 techProfileIDsForOnuLock sync.RWMutex
147
148 meterInfoForOnu map[string]*MeterInfo
149 meterInfoForOnuLock sync.RWMutex
150
151 onuGemInfo map[string]*OnuGemInfo
152 onuGemInfoLock sync.RWMutex
153
154 gemPortForPacketInInfo map[string]uint32
155 gemPortForPacketInInfoLock sync.RWMutex
156
157 flowIDsForGem map[uint32][]uint64
158 flowIDsForGemLock sync.RWMutex
159
160 mcastQueueForIntf map[uint32][]uint32
161 mcastQueueForIntfLock sync.RWMutex
162 mcastQueueForIntfLoadedFromKvStore bool
163
164 groupInfo map[string]*GroupInfo
165 groupInfoLock sync.RWMutex
166 // Local maps used for write-through-cache - end
Girish Gowdra4c3d4602021-07-22 16:33:37 -0700167
Girish Gowdra76a1b092021-07-28 10:07:04 -0700168 TechprofileRef tp.TechProfileIf
Abhilash S.L7f17e402019-03-15 17:40:41 +0530169}
170
Neha Sharma96b7bf22020-06-15 10:37:32 +0000171func newKVClient(ctx context.Context, storeType string, address string, timeout time.Duration) (kvstore.Client, error) {
172 logger.Infow(ctx, "kv-store-type", log.Fields{"store": storeType})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400173 switch storeType {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400174 case "etcd":
Neha Sharma96b7bf22020-06-15 10:37:32 +0000175 return kvstore.NewEtcdClient(ctx, address, timeout, log.FatalLevel)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400176 }
177 return nil, errors.New("unsupported-kv-store")
Abhilash S.L7f17e402019-03-15 17:40:41 +0530178}
179
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700180// SetKVClient sets the KV client and return a kv backend
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800181func SetKVClient(ctx context.Context, backend string, addr string, DeviceID string, basePathKvStore string) *db.Backend {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400182 // TODO : Make sure direct call to NewBackend is working fine with backend , currently there is some
183 // issue between kv store and backend , core is not calling NewBackend directly
Neha Sharma96b7bf22020-06-15 10:37:32 +0000184 kvClient, err := newKVClient(ctx, backend, addr, KvstoreTimeout)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400185 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000186 logger.Fatalw(ctx, "Failed to init KV client\n", log.Fields{"err": err})
Girish Gowdru0c588b22019-04-23 23:24:56 -0400187 return nil
188 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700189 // return db.NewBackend(ctx, backend, addr, KvstoreTimeout, fmt.Sprintf(BasePathKvStore, basePathKvStore, DeviceID))
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700190
sbarbaria8910ba2019-11-05 10:12:23 -0500191 kvbackend := &db.Backend{
Girish Gowdru0c588b22019-04-23 23:24:56 -0400192 Client: kvClient,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700193 StoreType: backend,
Neha Sharma3f221ae2020-04-29 19:02:12 +0000194 Address: addr,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700195 Timeout: KvstoreTimeout,
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800196 PathPrefix: fmt.Sprintf(BasePathKvStore, basePathKvStore, DeviceID)}
Abhilash S.L7f17e402019-03-15 17:40:41 +0530197
Girish Gowdru0c588b22019-04-23 23:24:56 -0400198 return kvbackend
Abhilash S.L7f17e402019-03-15 17:40:41 +0530199}
200
Holger Hildebrandt143b5be2023-02-10 08:28:15 +0000201// CloseKVClient closes open KV clients
202func (rsrcMgr *OpenOltResourceMgr) CloseKVClient(ctx context.Context) {
203 if rsrcMgr.KVStore != nil {
204 rsrcMgr.KVStore.Client.Close(ctx)
205 rsrcMgr.KVStore = nil
206 }
207 if rsrcMgr.PonRsrMgr != nil {
208 rsrcMgr.PonRsrMgr.CloseKVClient(ctx)
209 }
210}
211
Gamze Abakafee36392019-10-03 11:17:24 +0000212// NewResourceMgr init a New resource manager instance which in turn instantiates pon resource manager
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700213// instances according to technology. Initializes the default resource ranges for all
214// the resources.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700215func NewResourceMgr(ctx context.Context, PonIntfID uint32, deviceID string, KVStoreAddress string, kvStoreType string, deviceType string, devInfo *openolt.DeviceInfo, basePathKvStore string) *OpenOltResourceMgr {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400216 var ResourceMgr OpenOltResourceMgr
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700217 logger.Debugf(ctx, "Init new resource manager , ponIf: %v, address: %s, device-id: %s", PonIntfID, KVStoreAddress, deviceID)
218 ResourceMgr.PonIntfID = PonIntfID
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700219 ResourceMgr.DeviceID = deviceID
Neha Sharma3f221ae2020-04-29 19:02:12 +0000220 ResourceMgr.Address = KVStoreAddress
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700221 ResourceMgr.DeviceType = deviceType
222 ResourceMgr.DevInfo = devInfo
Abhilash S.L7f17e402019-03-15 17:40:41 +0530223
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700224 Backend := kvStoreType
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800225 ResourceMgr.KVStore = SetKVClient(ctx, Backend, ResourceMgr.Address, deviceID, basePathKvStore)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400226 if ResourceMgr.KVStore == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000227 logger.Error(ctx, "Failed to setup KV store")
Girish Gowdru0c588b22019-04-23 23:24:56 -0400228 }
Girish Gowdra38d533d2020-03-30 20:38:51 -0700229
Girish Gowdru0c588b22019-04-23 23:24:56 -0400230 // TODO self.args = registry('main').get_args()
Abhilash S.L7f17e402019-03-15 17:40:41 +0530231
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700232 // Create a separate Resource Manager instance for each range. This assumes that
Girish Gowdru0c588b22019-04-23 23:24:56 -0400233 // each technology is represented by only a single range
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700234 for _, TechRange := range devInfo.Ranges {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700235 for _, intfID := range TechRange.IntfIds {
236 if intfID == PonIntfID {
237 technology := TechRange.Technology
238 logger.Debugf(ctx, "Device info technology %s, intf-id %v", technology, PonIntfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000239
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700240 rsrMgr, err := ponrmgr.NewPONResourceManager(ctx, technology, deviceType, deviceID,
241 Backend, ResourceMgr.Address, basePathKvStore)
242 if err != nil {
243 logger.Errorf(ctx, "Failed to create pon resource manager instance for technology %s", technology)
244 return nil
245 }
246 ResourceMgr.PonRsrMgr = rsrMgr
247 // self.initialize_device_resource_range_and_pool(resource_mgr, global_resource_mgr, arange)
248 InitializeDeviceResourceRangeAndPool(ctx, rsrMgr, TechRange, devInfo)
249 if err := ResourceMgr.PonRsrMgr.InitDeviceResourcePoolForIntf(ctx, intfID); err != nil {
250 logger.Fatal(ctx, "failed-to-initialize-device-resource-pool-intf-id-%v-device-id", ResourceMgr.PonIntfID, ResourceMgr.DeviceID)
251 return nil
252 }
253 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400254 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400255 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700256
257 ResourceMgr.InitLocalCache()
yasin saplibddc2d72022-02-08 13:10:17 +0000258 if err := ResourceMgr.LoadLocalCacheFromKVStore(ctx); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000259 logger.Error(ctx, "failed-to-load-local-cache-from-kvstore")
260 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000261 logger.Info(ctx, "Initialization of resource manager success!")
Girish Gowdru0c588b22019-04-23 23:24:56 -0400262 return &ResourceMgr
Abhilash S.L7f17e402019-03-15 17:40:41 +0530263}
264
Joey Armstrong3f0e2422023-07-05 18:25:41 -0400265// InitLocalCache initializes local maps used for write-through-cache
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700266func (rsrcMgr *OpenOltResourceMgr) InitLocalCache() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700267 rsrcMgr.allocIDsForOnu = make(map[string][]uint32)
268 rsrcMgr.gemPortIDsForOnu = make(map[string][]uint32)
269 rsrcMgr.techProfileIDsForOnu = make(map[string][]uint32)
270 rsrcMgr.meterInfoForOnu = make(map[string]*MeterInfo)
271 rsrcMgr.onuGemInfo = make(map[string]*OnuGemInfo)
272 rsrcMgr.gemPortForPacketInInfo = make(map[string]uint32)
273 rsrcMgr.flowIDsForGem = make(map[uint32][]uint64)
274 rsrcMgr.mcastQueueForIntf = make(map[uint32][]uint32)
275 rsrcMgr.groupInfo = make(map[string]*GroupInfo)
276}
277
Joey Armstrong3f0e2422023-07-05 18:25:41 -0400278// LoadLocalCacheFromKVStore loads local maps
yasin saplibddc2d72022-02-08 13:10:17 +0000279func (rsrcMgr *OpenOltResourceMgr) LoadLocalCacheFromKVStore(ctx context.Context) error {
yasin sapli9e4c5092022-02-01 13:52:33 +0000280
281 //List all the keys for OnuGemInfo
yasin saplibddc2d72022-02-08 13:10:17 +0000282 prefixPath := fmt.Sprintf(OnuGemInfoPathPathPrefix, rsrcMgr.PonIntfID)
yasin sapli9e4c5092022-02-01 13:52:33 +0000283 keys, err := rsrcMgr.KVStore.List(ctx, prefixPath)
284 logger.Debug(ctx, "load-local-cache-from-KV-store-started")
285 if err != nil {
286 logger.Errorf(ctx, "failed-to-list-keys-from-path-%s", prefixPath)
287 return err
288 }
289 for path := range keys {
290 var Val []byte
291 var onugem OnuGemInfo
292 // Get rid of the path prefix
293 stringToBeReplaced := rsrcMgr.KVStore.PathPrefix + "/"
294 replacedWith := ""
295 path = strings.Replace(path, stringToBeReplaced, replacedWith, 1)
296
297 value, err := rsrcMgr.KVStore.Get(ctx, path)
298 if err != nil {
299 logger.Errorw(ctx, "failed-to-get-from-kv-store", log.Fields{"path": path})
300 return err
301 } else if value == nil {
302 logger.Debug(ctx, "no-onugeminfo-for-path", log.Fields{"path": path})
303 continue
304 }
305 if Val, err = kvstore.ToByte(value.Value); err != nil {
306 logger.Error(ctx, "failed-to-covert-to-byte-array")
307 return err
308 }
309 if err = json.Unmarshal(Val, &onugem); err != nil {
310 logger.Error(ctx, "failed-to-unmarshall")
311 return err
312 }
313 logger.Debugw(ctx, "found-onugeminfo-from-path", log.Fields{"path": path, "onuGemInfo": onugem})
314
315 rsrcMgr.onuGemInfoLock.Lock()
316 rsrcMgr.onuGemInfo[path] = &onugem
317 rsrcMgr.onuGemInfoLock.Unlock()
318
319 }
320 logger.Debug(ctx, "load-local-cache-from-KV-store-finished")
321 return nil
322}
323
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700324// InitializeDeviceResourceRangeAndPool initializes the resource range pool according to the sharing type, then apply
325// device specific information. If KV doesn't exist
326// or is broader than the device, the device's information will
327// dictate the range limits
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700328func InitializeDeviceResourceRangeAndPool(ctx context.Context, ponRMgr *ponrmgr.PONResourceManager,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700329 techRange *openolt.DeviceInfo_DeviceResourceRanges, devInfo *openolt.DeviceInfo) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700330 // var ONUIDShared, AllocIDShared, GEMPortIDShared openolt.DeviceInfo_DeviceResourceRanges_Pool_SharingType
331 var ONUIDStart, ONUIDEnd, AllocIDStart, AllocIDEnd, GEMPortIDStart, GEMPortIDEnd uint32
332 var ONUIDShared, AllocIDShared, GEMPortIDShared, FlowIDShared uint32
333
334 // The below variables are just dummy and needed to pass as arguments to InitDefaultPONResourceRanges function.
335 // The openolt adapter does not need flowIDs to be managed as it is managed on the OLT device
336 // The UNI IDs are dynamically generated by openonu adapter for every discovered UNI.
337 var flowIDDummyStart, flowIDDummyEnd uint32 = 1, 2
338 var uniIDDummyStart, uniIDDummyEnd uint32 = 0, 1
Abhilash S.L7f17e402019-03-15 17:40:41 +0530339
Girish Gowdru0c588b22019-04-23 23:24:56 -0400340 // init the resource range pool according to the sharing type
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700341 logger.Debugw(ctx, "Device info init", log.Fields{"technology": techRange.Technology,
342 "onu_id_start": ONUIDStart, "onu_id_end": ONUIDEnd,
343 "alloc_id_start": AllocIDStart, "alloc_id_end": AllocIDEnd,
344 "gemport_id_start": GEMPortIDStart, "gemport_id_end": GEMPortIDEnd,
345 "intf_ids": techRange.IntfIds,
346 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700347 for _, RangePool := range techRange.Pools {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700348 // FIXME: Remove hardcoding
Girish Gowdru0c588b22019-04-23 23:24:56 -0400349 if RangePool.Type == openolt.DeviceInfo_DeviceResourceRanges_Pool_ONU_ID {
350 ONUIDStart = RangePool.Start
351 ONUIDEnd = RangePool.End
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700352 ONUIDShared = uint32(RangePool.Sharing)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400353 } else if RangePool.Type == openolt.DeviceInfo_DeviceResourceRanges_Pool_ALLOC_ID {
354 AllocIDStart = RangePool.Start
355 AllocIDEnd = RangePool.End
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700356 AllocIDShared = uint32(RangePool.Sharing)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400357 } else if RangePool.Type == openolt.DeviceInfo_DeviceResourceRanges_Pool_GEMPORT_ID {
358 GEMPortIDStart = RangePool.Start
359 GEMPortIDEnd = RangePool.End
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700360 GEMPortIDShared = uint32(RangePool.Sharing)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400361 }
362 }
Abhilash S.L7f17e402019-03-15 17:40:41 +0530363
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700364 ponRMgr.InitDefaultPONResourceRanges(ctx, ONUIDStart, ONUIDEnd, ONUIDShared,
365 AllocIDStart, AllocIDEnd, AllocIDShared,
366 GEMPortIDStart, GEMPortIDEnd, GEMPortIDShared,
367 flowIDDummyStart, flowIDDummyEnd, FlowIDShared, uniIDDummyStart, uniIDDummyEnd,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700368 devInfo.PonPorts, techRange.IntfIds)
Abhilash S.L7f17e402019-03-15 17:40:41 +0530369
Abhilash S.L7f17e402019-03-15 17:40:41 +0530370}
371
Devmalya Paul495b94a2019-08-27 19:42:00 -0400372// Delete clears used resources for the particular olt device being deleted
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700373func (rsrcMgr *OpenOltResourceMgr) Delete(ctx context.Context, intfID uint32) error {
374 if err := rsrcMgr.PonRsrMgr.ClearDeviceResourcePoolForIntf(ctx, intfID); err != nil {
375 logger.Debug(ctx, "Failed to clear device resource pool")
376 return err
Devmalya Paul495b94a2019-08-27 19:42:00 -0400377 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000378 logger.Debug(ctx, "Cleared device resource pool")
Devmalya Paul495b94a2019-08-27 19:42:00 -0400379 return nil
380}
Abhilash S.L7f17e402019-03-15 17:40:41 +0530381
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700382// GetONUID returns the available onuID for the given pon-port
yasin saplibddc2d72022-02-08 13:10:17 +0000383func (rsrcMgr *OpenOltResourceMgr) GetONUID(ctx context.Context) (uint32, error) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400384 // Get ONU id for a provided pon interface ID.
yasin saplibddc2d72022-02-08 13:10:17 +0000385 onuID, err := rsrcMgr.TechprofileRef.GetResourceID(ctx, rsrcMgr.PonIntfID,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400386 ponrmgr.ONU_ID, 1)
387 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000388 logger.Errorf(ctx, "Failed to get resource for interface %d for type %s",
yasin saplibddc2d72022-02-08 13:10:17 +0000389 rsrcMgr.PonIntfID, ponrmgr.ONU_ID)
cbabuabf02352019-10-15 13:14:56 +0200390 return 0, err
Girish Gowdru0c588b22019-04-23 23:24:56 -0400391 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700392 if len(onuID) > 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700393 return onuID[0], err
Girish Gowdru0c588b22019-04-23 23:24:56 -0400394 }
Abhilash S.L7f17e402019-03-15 17:40:41 +0530395
Girish Gowdra950326e2021-11-05 12:43:24 -0700396 return 0, fmt.Errorf("no-onu-id-allocated")
Abhilash S.L8ee90712019-04-29 16:24:22 +0530397}
398
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700399// UpdateAllocIdsForOnu updates alloc ids in kv store for a given pon interface id, onu id and uni id
yasin saplibddc2d72022-02-08 13:10:17 +0000400func (rsrcMgr *OpenOltResourceMgr) UpdateAllocIdsForOnu(ctx context.Context, onuID uint32, uniID uint32, allocIDs []uint32) error {
Abhilash S.L7f17e402019-03-15 17:40:41 +0530401
yasin saplibddc2d72022-02-08 13:10:17 +0000402 intfOnuIDuniID := fmt.Sprintf("%d,%d,%d", rsrcMgr.PonIntfID, onuID, uniID)
Gamze Abaka745ccb72021-11-18 11:29:58 +0000403
404 // Note: in case the write to DB fails there could be inconsistent data between cache and db.
405 // Although this is highly unlikely with DB retries in place, this is something we have to deal with in the next release
406 if err := rsrcMgr.PonRsrMgr.UpdateAllocIdsForOnu(ctx, intfOnuIDuniID, allocIDs); err != nil {
407 logger.Errorw(ctx, "Failed to update alloc ids for onu", log.Fields{"err": err})
408 return err
409 }
410
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700411 // update cache
412 rsrcMgr.allocIDsForOnuLock.Lock()
413 rsrcMgr.allocIDsForOnu[intfOnuIDuniID] = allocIDs
414 rsrcMgr.allocIDsForOnuLock.Unlock()
Gamze Abaka745ccb72021-11-18 11:29:58 +0000415 return nil
Abhilash S.L7f17e402019-03-15 17:40:41 +0530416}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700417
418// GetCurrentGEMPortIDsForOnu returns gem ports for given pon interface , onu id and uni id
yasin saplibddc2d72022-02-08 13:10:17 +0000419func (rsrcMgr *OpenOltResourceMgr) GetCurrentGEMPortIDsForOnu(ctx context.Context, onuID uint32,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700420 uniID uint32) []uint32 {
Abhilash S.L7f17e402019-03-15 17:40:41 +0530421
yasin saplibddc2d72022-02-08 13:10:17 +0000422 intfOnuIDuniID := fmt.Sprintf("%d,%d,%d", rsrcMgr.PonIntfID, onuID, uniID)
Abhilash S.L7f17e402019-03-15 17:40:41 +0530423
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700424 // fetch from cache
425 rsrcMgr.gemPortIDsForOnuLock.RLock()
426 gemIDs, ok := rsrcMgr.gemPortIDsForOnu[intfOnuIDuniID]
427 rsrcMgr.gemPortIDsForOnuLock.RUnlock()
428 if ok {
429 return gemIDs
430 }
431 /* Get gem ports for given pon interface , onu id and uni id. */
432 gemIDs = rsrcMgr.PonRsrMgr.GetCurrentGEMPortIDsForOnu(ctx, intfOnuIDuniID)
433
434 // update cache
435 rsrcMgr.gemPortIDsForOnuLock.Lock()
436 rsrcMgr.gemPortIDsForOnu[intfOnuIDuniID] = gemIDs
437 rsrcMgr.gemPortIDsForOnuLock.Unlock()
438
439 return gemIDs
Abhilash S.L7f17e402019-03-15 17:40:41 +0530440}
441
Gamze Abakafee36392019-10-03 11:17:24 +0000442// GetCurrentAllocIDsForOnu returns alloc ids for given pon interface and onu id
yasin saplibddc2d72022-02-08 13:10:17 +0000443func (rsrcMgr *OpenOltResourceMgr) GetCurrentAllocIDsForOnu(ctx context.Context, onuID uint32, uniID uint32) []uint32 {
Abhilash S.L7f17e402019-03-15 17:40:41 +0530444
yasin saplibddc2d72022-02-08 13:10:17 +0000445 intfOnuIDuniID := fmt.Sprintf("%d,%d,%d", rsrcMgr.PonIntfID, onuID, uniID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700446 // fetch from cache
447 rsrcMgr.allocIDsForOnuLock.RLock()
448 allocIDs, ok := rsrcMgr.allocIDsForOnu[intfOnuIDuniID]
449 rsrcMgr.allocIDsForOnuLock.RUnlock()
450 if ok {
451 return allocIDs
Girish Gowdru0c588b22019-04-23 23:24:56 -0400452 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700453 allocIDs = rsrcMgr.PonRsrMgr.GetCurrentAllocIDForOnu(ctx, intfOnuIDuniID)
454
455 // update cache
456 rsrcMgr.allocIDsForOnuLock.Lock()
457 rsrcMgr.allocIDsForOnu[intfOnuIDuniID] = allocIDs
458 rsrcMgr.allocIDsForOnuLock.Unlock()
459
460 return allocIDs
Gamze Abakafee36392019-10-03 11:17:24 +0000461}
462
463// RemoveAllocIDForOnu removes the alloc id for given pon interface, onu id, uni id and alloc id
yasin saplibddc2d72022-02-08 13:10:17 +0000464func (rsrcMgr *OpenOltResourceMgr) RemoveAllocIDForOnu(ctx context.Context, onuID uint32, uniID uint32, allocID uint32) {
465 allocIDs := rsrcMgr.GetCurrentAllocIDsForOnu(ctx, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +0000466 for i := 0; i < len(allocIDs); i++ {
467 if allocIDs[i] == allocID {
468 allocIDs = append(allocIDs[:i], allocIDs[i+1:]...)
469 break
470 }
471 }
yasin saplibddc2d72022-02-08 13:10:17 +0000472 err := rsrcMgr.UpdateAllocIdsForOnu(ctx, onuID, uniID, allocIDs)
Gamze Abakafee36392019-10-03 11:17:24 +0000473 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700474 logger.Errorf(ctx, "Failed to Remove Alloc Id For Onu. intfID %d onuID %d uniID %d allocID %d",
yasin saplibddc2d72022-02-08 13:10:17 +0000475 rsrcMgr.PonIntfID, onuID, uniID, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000476 }
477}
478
479// RemoveGemPortIDForOnu removes the gem port id for given pon interface, onu id, uni id and gem port id
yasin saplibddc2d72022-02-08 13:10:17 +0000480func (rsrcMgr *OpenOltResourceMgr) RemoveGemPortIDForOnu(ctx context.Context, onuID uint32, uniID uint32, gemPortID uint32) {
481 gemPortIDs := rsrcMgr.GetCurrentGEMPortIDsForOnu(ctx, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +0000482 for i := 0; i < len(gemPortIDs); i++ {
483 if gemPortIDs[i] == gemPortID {
484 gemPortIDs = append(gemPortIDs[:i], gemPortIDs[i+1:]...)
485 break
486 }
487 }
yasin saplibddc2d72022-02-08 13:10:17 +0000488 err := rsrcMgr.UpdateGEMPortIDsForOnu(ctx, onuID, uniID, gemPortIDs)
Gamze Abakafee36392019-10-03 11:17:24 +0000489 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700490 logger.Errorf(ctx, "Failed to Remove Gem Id For Onu. intfID %d onuID %d uniID %d gemPortId %d",
yasin saplibddc2d72022-02-08 13:10:17 +0000491 rsrcMgr.PonIntfID, onuID, uniID, gemPortID)
Gamze Abakafee36392019-10-03 11:17:24 +0000492 }
Abhilash S.L7f17e402019-03-15 17:40:41 +0530493}
494
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700495// UpdateGEMPortIDsForOnu updates gemport ids on to the kv store for a given pon port, onu id and uni id
yasin saplibddc2d72022-02-08 13:10:17 +0000496func (rsrcMgr *OpenOltResourceMgr) UpdateGEMPortIDsForOnu(ctx context.Context, onuID uint32,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700497 uniID uint32, gemIDs []uint32) error {
yasin saplibddc2d72022-02-08 13:10:17 +0000498 intfOnuIDuniID := fmt.Sprintf("%d,%d,%d", rsrcMgr.PonIntfID, onuID, uniID)
Gamze Abaka745ccb72021-11-18 11:29:58 +0000499
500 if err := rsrcMgr.PonRsrMgr.UpdateGEMPortIDsForOnu(ctx, intfOnuIDuniID, gemIDs); err != nil {
501 logger.Errorw(ctx, "Failed to update gem port ids for onu", log.Fields{"err": err})
502 return err
503 }
504
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700505 // update cache
506 rsrcMgr.gemPortIDsForOnuLock.Lock()
507 rsrcMgr.gemPortIDsForOnu[intfOnuIDuniID] = gemIDs
508 rsrcMgr.gemPortIDsForOnuLock.Unlock()
Gamze Abaka745ccb72021-11-18 11:29:58 +0000509 return nil
Abhilash S.L7f17e402019-03-15 17:40:41 +0530510}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700511
512// FreeonuID releases(make free) onu id for a particular pon-port
yasin saplibddc2d72022-02-08 13:10:17 +0000513func (rsrcMgr *OpenOltResourceMgr) FreeonuID(ctx context.Context, onuID []uint32) {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -0700514 if len(onuID) == 0 {
515 logger.Info(ctx, "onu id slice is nil, nothing to free")
516 return
517 }
yasin saplibddc2d72022-02-08 13:10:17 +0000518 if err := rsrcMgr.TechprofileRef.FreeResourceID(ctx, rsrcMgr.PonIntfID, ponrmgr.ONU_ID, onuID); err != nil {
Matteo Scandolo84585372021-03-18 14:21:22 -0700519 logger.Errorw(ctx, "error-while-freeing-onu-id", log.Fields{
yasin saplibddc2d72022-02-08 13:10:17 +0000520 "intf-id": rsrcMgr.PonIntfID,
Matteo Scandolo84585372021-03-18 14:21:22 -0700521 "onu-id": onuID,
522 "err": err.Error(),
523 })
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -0700524 } else {
yasin saplibddc2d72022-02-08 13:10:17 +0000525 logger.Infow(ctx, "freed onu id", log.Fields{"intfID": rsrcMgr.PonIntfID, "onuID": onuID})
Matteo Scandolo84585372021-03-18 14:21:22 -0700526 }
Abhilash S.L7f17e402019-03-15 17:40:41 +0530527}
528
Gamze Abakafee36392019-10-03 11:17:24 +0000529// FreeAllocID frees AllocID on the PON resource pool and also frees the allocID association
530// for the given OLT device.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700531// The caller should ensure that this is a blocking call and this operation is serialized for
532// the ONU so as not cause resource corruption since there are no mutexes used here.
Girish Gowdraf3728b12022-02-02 21:46:51 -0800533// Setting freeFromResourcePool to false will not clear it from the resource pool but only
534// clear it for the given pon/onu/uni
yasin saplibddc2d72022-02-08 13:10:17 +0000535func (rsrcMgr *OpenOltResourceMgr) FreeAllocID(ctx context.Context, onuID uint32,
Girish Gowdraf3728b12022-02-02 21:46:51 -0800536 uniID uint32, allocID uint32, freeFromResourcePool bool) {
Girish Gowdrab77ded92020-04-08 11:45:05 -0700537
yasin saplibddc2d72022-02-08 13:10:17 +0000538 rsrcMgr.RemoveAllocIDForOnu(ctx, onuID, uniID, allocID)
Girish Gowdraf3728b12022-02-02 21:46:51 -0800539 if freeFromResourcePool {
540 allocIDs := make([]uint32, 0)
541 allocIDs = append(allocIDs, allocID)
yasin saplibddc2d72022-02-08 13:10:17 +0000542 if err := rsrcMgr.TechprofileRef.FreeResourceID(ctx, rsrcMgr.PonIntfID, ponrmgr.ALLOC_ID, allocIDs); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800543 logger.Errorw(ctx, "error-while-freeing-alloc-id", log.Fields{
yasin saplibddc2d72022-02-08 13:10:17 +0000544 "intf-id": rsrcMgr.PonIntfID,
Girish Gowdraf3728b12022-02-02 21:46:51 -0800545 "onu-id": onuID,
546 "err": err.Error(),
547 })
548 }
Matteo Scandolo84585372021-03-18 14:21:22 -0700549 }
Gamze Abakafee36392019-10-03 11:17:24 +0000550}
551
552// FreeGemPortID frees GemPortID on the PON resource pool and also frees the gemPortID association
553// for the given OLT device.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700554// The caller should ensure that this is a blocking call and this operation is serialized for
555// the ONU so as not cause resource corruption since there are no mutexes used here.
yasin saplibddc2d72022-02-08 13:10:17 +0000556func (rsrcMgr *OpenOltResourceMgr) FreeGemPortID(ctx context.Context, onuID uint32,
Gamze Abakafee36392019-10-03 11:17:24 +0000557 uniID uint32, gemPortID uint32) {
yasin saplibddc2d72022-02-08 13:10:17 +0000558 rsrcMgr.RemoveGemPortIDForOnu(ctx, onuID, uniID, gemPortID)
Girish Gowdrab77ded92020-04-08 11:45:05 -0700559
Gamze Abakafee36392019-10-03 11:17:24 +0000560 gemPortIDs := make([]uint32, 0)
561 gemPortIDs = append(gemPortIDs, gemPortID)
yasin saplibddc2d72022-02-08 13:10:17 +0000562 if err := rsrcMgr.TechprofileRef.FreeResourceID(ctx, rsrcMgr.PonIntfID, ponrmgr.GEMPORT_ID, gemPortIDs); err != nil {
Matteo Scandolo84585372021-03-18 14:21:22 -0700563 logger.Errorw(ctx, "error-while-freeing-gem-port-id", log.Fields{
yasin saplibddc2d72022-02-08 13:10:17 +0000564 "intf-id": rsrcMgr.PonIntfID,
Matteo Scandolo84585372021-03-18 14:21:22 -0700565 "onu-id": onuID,
566 "err": err.Error(),
567 })
568 }
Gamze Abakafee36392019-10-03 11:17:24 +0000569}
570
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700571// FreePONResourcesForONU make the pon resources free for a given pon interface and onu id
yasin saplibddc2d72022-02-08 13:10:17 +0000572func (rsrcMgr *OpenOltResourceMgr) FreePONResourcesForONU(ctx context.Context, onuID uint32, uniID uint32) {
Abhilash S.L7f17e402019-03-15 17:40:41 +0530573
yasin saplibddc2d72022-02-08 13:10:17 +0000574 intfOnuIDuniID := fmt.Sprintf("%d,%d,%d", rsrcMgr.PonIntfID, onuID, uniID)
Abhilash S.L7f17e402019-03-15 17:40:41 +0530575
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700576 AllocIDs := rsrcMgr.PonRsrMgr.GetCurrentAllocIDForOnu(ctx, intfOnuIDuniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700577
yasin saplibddc2d72022-02-08 13:10:17 +0000578 if err := rsrcMgr.TechprofileRef.FreeResourceID(ctx, rsrcMgr.PonIntfID,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400579 ponrmgr.ALLOC_ID,
Matteo Scandolo84585372021-03-18 14:21:22 -0700580 AllocIDs); err != nil {
581 logger.Errorw(ctx, "error-while-freeing-all-alloc-ids-for-onu", log.Fields{
yasin saplibddc2d72022-02-08 13:10:17 +0000582 "intf-id": rsrcMgr.PonIntfID,
Matteo Scandolo84585372021-03-18 14:21:22 -0700583 "onu-id": onuID,
584 "err": err.Error(),
585 })
586 }
Abhilash S.L7f17e402019-03-15 17:40:41 +0530587
Gamze Abaka745ccb72021-11-18 11:29:58 +0000588 //update cache
589 rsrcMgr.allocIDsForOnuLock.Lock()
590 delete(rsrcMgr.allocIDsForOnu, intfOnuIDuniID)
591 rsrcMgr.allocIDsForOnuLock.Unlock()
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700592
Gamze Abaka745ccb72021-11-18 11:29:58 +0000593 GEMPortIDs := rsrcMgr.PonRsrMgr.GetCurrentGEMPortIDsForOnu(ctx, intfOnuIDuniID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700594
yasin saplibddc2d72022-02-08 13:10:17 +0000595 if err := rsrcMgr.TechprofileRef.FreeResourceID(ctx, rsrcMgr.PonIntfID,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400596 ponrmgr.GEMPORT_ID,
Matteo Scandolo84585372021-03-18 14:21:22 -0700597 GEMPortIDs); err != nil {
598 logger.Errorw(ctx, "error-while-freeing-all-gem-port-ids-for-onu", log.Fields{
yasin saplibddc2d72022-02-08 13:10:17 +0000599 "intf-id": rsrcMgr.PonIntfID,
Matteo Scandolo84585372021-03-18 14:21:22 -0700600 "onu-id": onuID,
601 "err": err.Error(),
602 })
603 }
Abhilash S.L7f17e402019-03-15 17:40:41 +0530604
Gamze Abaka745ccb72021-11-18 11:29:58 +0000605 // update cache
606 rsrcMgr.gemPortIDsForOnuLock.Lock()
607 delete(rsrcMgr.gemPortIDsForOnu, intfOnuIDuniID)
608 rsrcMgr.gemPortIDsForOnuLock.Unlock()
609
Girish Gowdru0c588b22019-04-23 23:24:56 -0400610 // Clear resource map associated with (pon_intf_id, gemport_id) tuple.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700611 rsrcMgr.PonRsrMgr.RemoveResourceMap(ctx, intfOnuIDuniID)
Abhilash S.L7f17e402019-03-15 17:40:41 +0530612}
613
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700614// IsFlowOnKvStore checks if the given flowID is present on the kv store
615// Returns true if the flowID is found, otherwise it returns false
yasin saplibddc2d72022-02-08 13:10:17 +0000616func (rsrcMgr *OpenOltResourceMgr) IsFlowOnKvStore(ctx context.Context, onuID int32, flowID uint64) (bool, error) {
yasin saplid0566272021-12-21 09:10:30 +0000617 var anyError error
Abhilash S.L7f17e402019-03-15 17:40:41 +0530618
yasin saplid0566272021-12-21 09:10:30 +0000619 // In case of nni trap flow
620 if onuID == -1 {
yasin saplibddc2d72022-02-08 13:10:17 +0000621 nniTrapflowIDs, err := rsrcMgr.GetFlowIDsForGem(ctx, NNI)
yasin saplid0566272021-12-21 09:10:30 +0000622 if err != nil {
623 logger.Warnw(ctx, "failed-to-get-nni-trap-flowIDs", log.Fields{"err": err})
624 return false, err
625 }
626 for _, id := range nniTrapflowIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700627 if flowID == id {
yasin saplid0566272021-12-21 09:10:30 +0000628 return true, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400629 }
630 }
631 }
yasin saplid0566272021-12-21 09:10:30 +0000632
yasin saplibddc2d72022-02-08 13:10:17 +0000633 path := fmt.Sprintf(OnuGemInfoPath, rsrcMgr.PonIntfID, onuID)
yasin saplid0566272021-12-21 09:10:30 +0000634 rsrcMgr.onuGemInfoLock.RLock()
635 val, ok := rsrcMgr.onuGemInfo[path]
636 rsrcMgr.onuGemInfoLock.RUnlock()
637
638 if ok {
639 for _, gem := range val.GemPorts {
yasin saplibddc2d72022-02-08 13:10:17 +0000640 flowIDs, err := rsrcMgr.GetFlowIDsForGem(ctx, gem)
yasin saplid0566272021-12-21 09:10:30 +0000641 if err != nil {
642 anyError = err
643 logger.Warnw(ctx, "failed-to-get-flowIDs-for-gem", log.Fields{"err": err, "onuID": onuID, "gem": gem})
644 } else {
645 for _, id := range flowIDs {
646 if flowID == id {
647 return true, nil
648 }
649 }
650 }
651 }
652 }
653 return false, anyError
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400654}
Manikkaraj kb1d51442019-07-23 10:41:02 -0400655
salmansiddiqui7ac62132019-08-22 03:58:50 +0000656// GetTechProfileIDForOnu fetches Tech-Profile-ID from the KV-Store for the given onu based on the path
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700657// This path is formed as the following: {intfID, onuID, uniID}/tp_id
yasin saplibddc2d72022-02-08 13:10:17 +0000658func (rsrcMgr *OpenOltResourceMgr) GetTechProfileIDForOnu(ctx context.Context, onuID uint32, uniID uint32) []uint32 {
659 Path := fmt.Sprintf(tpIDPathSuffix, rsrcMgr.PonIntfID, onuID, uniID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700660 // fetch from cache
661 rsrcMgr.techProfileIDsForOnuLock.RLock()
662 tpIDs, ok := rsrcMgr.techProfileIDsForOnu[Path]
663 rsrcMgr.techProfileIDsForOnuLock.RUnlock()
664 if ok {
665 return tpIDs
666 }
667 Value, err := rsrcMgr.KVStore.Get(ctx, Path)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400668 if err == nil {
669 if Value != nil {
670 Val, err := kvstore.ToByte(Value.Value)
671 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700672 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": err})
673 return tpIDs
Manikkaraj kb1d51442019-07-23 10:41:02 -0400674 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700675 if err = json.Unmarshal(Val, &tpIDs); err != nil {
676 logger.Error(ctx, "Failed to unmarshal", log.Fields{"err": err})
677 return tpIDs
Manikkaraj kb1d51442019-07-23 10:41:02 -0400678 }
679 }
680 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000681 logger.Errorf(ctx, "Failed to get TP id from kvstore for path %s", Path)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400682 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700683 logger.Debugf(ctx, "Getting TP id %d from path %s", tpIDs, Path)
684
685 // update cache
686 rsrcMgr.techProfileIDsForOnuLock.Lock()
687 rsrcMgr.techProfileIDsForOnu[Path] = tpIDs
688 rsrcMgr.techProfileIDsForOnuLock.Unlock()
689
690 return tpIDs
Manikkaraj kb1d51442019-07-23 10:41:02 -0400691
692}
693
Gamze Abakafee36392019-10-03 11:17:24 +0000694// RemoveTechProfileIDsForOnu deletes all tech profile ids from the KV-Store for the given onu based on the path
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700695// This path is formed as the following: {intfID, onuID, uniID}/tp_id
yasin saplibddc2d72022-02-08 13:10:17 +0000696func (rsrcMgr *OpenOltResourceMgr) RemoveTechProfileIDsForOnu(ctx context.Context, onuID uint32, uniID uint32) error {
697 intfOnuUniID := fmt.Sprintf(tpIDPathSuffix, rsrcMgr.PonIntfID, onuID, uniID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700698
699 if err := rsrcMgr.KVStore.Delete(ctx, intfOnuUniID); err != nil {
700 logger.Errorw(ctx, "Failed to delete techprofile id resource in KV store", log.Fields{"path": intfOnuUniID})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400701 return err
702 }
Gamze Abaka745ccb72021-11-18 11:29:58 +0000703
704 // update cache
705 rsrcMgr.techProfileIDsForOnuLock.Lock()
706 delete(rsrcMgr.techProfileIDsForOnu, intfOnuUniID)
707 rsrcMgr.techProfileIDsForOnuLock.Unlock()
Manikkaraj kb1d51442019-07-23 10:41:02 -0400708 return nil
709}
710
Gamze Abakafee36392019-10-03 11:17:24 +0000711// RemoveTechProfileIDForOnu deletes a specific tech profile id from the KV-Store for the given onu based on the path
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700712// This path is formed as the following: {intfID, onuID, uniID}/tp_id
yasin saplibddc2d72022-02-08 13:10:17 +0000713func (rsrcMgr *OpenOltResourceMgr) RemoveTechProfileIDForOnu(ctx context.Context, onuID uint32, uniID uint32, tpID uint32) error {
714 tpIDList := rsrcMgr.GetTechProfileIDForOnu(ctx, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +0000715 for i, tpIDInList := range tpIDList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700716 if tpIDInList == tpID {
Gamze Abakafee36392019-10-03 11:17:24 +0000717 tpIDList = append(tpIDList[:i], tpIDList[i+1:]...)
718 }
719 }
yasin saplibddc2d72022-02-08 13:10:17 +0000720 intfOnuUniID := fmt.Sprintf(tpIDPathSuffix, rsrcMgr.PonIntfID, onuID, uniID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700721
Gamze Abakafee36392019-10-03 11:17:24 +0000722 Value, err := json.Marshal(tpIDList)
723 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000724 logger.Error(ctx, "failed to Marshal")
Gamze Abakafee36392019-10-03 11:17:24 +0000725 return err
726 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700727 if err = rsrcMgr.KVStore.Put(ctx, intfOnuUniID, Value); err != nil {
728 logger.Errorf(ctx, "Failed to update resource %s", intfOnuUniID)
Gamze Abakafee36392019-10-03 11:17:24 +0000729 return err
730 }
Gamze Abaka745ccb72021-11-18 11:29:58 +0000731
732 // update cache
733 rsrcMgr.techProfileIDsForOnuLock.Lock()
734 rsrcMgr.techProfileIDsForOnu[intfOnuUniID] = tpIDList
735 rsrcMgr.techProfileIDsForOnuLock.Unlock()
Gamze Abakafee36392019-10-03 11:17:24 +0000736 return err
737}
738
739// UpdateTechProfileIDForOnu updates (put) already present tech-profile-id for the given onu based on the path
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700740// This path is formed as the following: {intfID, onuID, uniID}/tp_id
yasin saplibddc2d72022-02-08 13:10:17 +0000741func (rsrcMgr *OpenOltResourceMgr) UpdateTechProfileIDForOnu(ctx context.Context, onuID uint32,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700742 uniID uint32, tpID uint32) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400743 var Value []byte
744 var err error
745
yasin saplibddc2d72022-02-08 13:10:17 +0000746 intfOnuUniID := fmt.Sprintf(tpIDPathSuffix, rsrcMgr.PonIntfID, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +0000747
yasin saplibddc2d72022-02-08 13:10:17 +0000748 tpIDList := rsrcMgr.GetTechProfileIDForOnu(ctx, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +0000749 for _, value := range tpIDList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700750 if value == tpID {
751 logger.Debugf(ctx, "tpID %d is already in tpIdList for the path %s", tpID, intfOnuUniID)
Gamze Abakafee36392019-10-03 11:17:24 +0000752 return err
753 }
754 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700755 logger.Debugf(ctx, "updating tp id %d on path %s", tpID, intfOnuUniID)
756 tpIDList = append(tpIDList, tpID)
757
Gamze Abakafee36392019-10-03 11:17:24 +0000758 Value, err = json.Marshal(tpIDList)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400759 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000760 logger.Error(ctx, "failed to Marshal")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400761 return err
762 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700763 if err = rsrcMgr.KVStore.Put(ctx, intfOnuUniID, Value); err != nil {
764 logger.Errorf(ctx, "Failed to update resource %s", intfOnuUniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400765 return err
766 }
Gamze Abaka745ccb72021-11-18 11:29:58 +0000767
768 // update cache
769 rsrcMgr.techProfileIDsForOnuLock.Lock()
770 rsrcMgr.techProfileIDsForOnu[intfOnuUniID] = tpIDList
771 rsrcMgr.techProfileIDsForOnuLock.Unlock()
Manikkaraj kb1d51442019-07-23 10:41:02 -0400772 return err
773}
774
Girish Gowdraa482f272021-03-24 23:04:19 -0700775// StoreMeterInfoForOnu updates the meter id in the KV-Store for the given onu based on the path
Gamze Abakafee36392019-10-03 11:17:24 +0000776// This path is formed as the following: <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
yasin saplibddc2d72022-02-08 13:10:17 +0000777func (rsrcMgr *OpenOltResourceMgr) StoreMeterInfoForOnu(ctx context.Context, Direction string, onuID uint32,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700778 uniID uint32, tpID uint32, meterInfo *MeterInfo) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400779 var Value []byte
780 var err error
yasin saplibddc2d72022-02-08 13:10:17 +0000781 intfOnuUniID := fmt.Sprintf(MeterIDPathSuffix, rsrcMgr.PonIntfID, onuID, uniID, tpID, Direction)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700782
Girish Gowdraa482f272021-03-24 23:04:19 -0700783 Value, err = json.Marshal(*meterInfo)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400784 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000785 logger.Error(ctx, "failed to Marshal meter config")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400786 return err
787 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700788 if err = rsrcMgr.KVStore.Put(ctx, intfOnuUniID, Value); err != nil {
789 logger.Errorf(ctx, "Failed to store meter into KV store %s", intfOnuUniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400790 return err
791 }
Gamze Abaka745ccb72021-11-18 11:29:58 +0000792
793 // update cache
794 rsrcMgr.meterInfoForOnuLock.Lock()
795 rsrcMgr.meterInfoForOnu[intfOnuUniID] = meterInfo
796 rsrcMgr.meterInfoForOnuLock.Unlock()
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700797 logger.Debugw(ctx, "meter info updated successfully", log.Fields{"path": intfOnuUniID, "meter-info": meterInfo})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400798 return err
799}
800
Girish Gowdraa482f272021-03-24 23:04:19 -0700801// GetMeterInfoForOnu fetches the meter id from the kv store for the given onu based on the path
Gamze Abakafee36392019-10-03 11:17:24 +0000802// This path is formed as the following: <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
yasin saplibddc2d72022-02-08 13:10:17 +0000803func (rsrcMgr *OpenOltResourceMgr) GetMeterInfoForOnu(ctx context.Context, Direction string, onuID uint32,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700804 uniID uint32, tpID uint32) (*MeterInfo, error) {
yasin saplibddc2d72022-02-08 13:10:17 +0000805 Path := fmt.Sprintf(MeterIDPathSuffix, rsrcMgr.PonIntfID, onuID, uniID, tpID, Direction)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700806
807 // get from cache
808 rsrcMgr.meterInfoForOnuLock.RLock()
809 val, ok := rsrcMgr.meterInfoForOnu[Path]
810 rsrcMgr.meterInfoForOnuLock.RUnlock()
811 if ok {
812 return val, nil
813 }
814
Girish Gowdraa482f272021-03-24 23:04:19 -0700815 var meterInfo MeterInfo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700816 Value, err := rsrcMgr.KVStore.Get(ctx, Path)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400817 if err == nil {
818 if Value != nil {
Girish Gowdraa482f272021-03-24 23:04:19 -0700819 logger.Debug(ctx, "Found meter info in KV store", log.Fields{"Direction": Direction})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000820 Val, er := kvstore.ToByte(Value.Value)
821 if er != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700822 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": er})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000823 return nil, er
Manikkaraj kb1d51442019-07-23 10:41:02 -0400824 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700825 if er = json.Unmarshal(Val, &meterInfo); er != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700826 logger.Error(ctx, "Failed to unmarshal meter info", log.Fields{"err": er})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000827 return nil, er
Manikkaraj kb1d51442019-07-23 10:41:02 -0400828 }
829 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000830 logger.Debug(ctx, "meter-does-not-exists-in-KVStore")
Manikkaraj kb1d51442019-07-23 10:41:02 -0400831 return nil, err
832 }
833 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000834 logger.Errorf(ctx, "Failed to get Meter config from kvstore for path %s", Path)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400835
836 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700837 // update cache
838 rsrcMgr.meterInfoForOnuLock.Lock()
839 rsrcMgr.meterInfoForOnu[Path] = &meterInfo
840 rsrcMgr.meterInfoForOnuLock.Unlock()
841
Girish Gowdraa482f272021-03-24 23:04:19 -0700842 return &meterInfo, err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400843}
844
Girish Gowdraa482f272021-03-24 23:04:19 -0700845// HandleMeterInfoRefCntUpdate increments or decrements the reference counter for a given meter.
846// When reference count becomes 0, it clears the meter information from the kv store
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700847func (rsrcMgr *OpenOltResourceMgr) HandleMeterInfoRefCntUpdate(ctx context.Context, Direction string,
yasin saplibddc2d72022-02-08 13:10:17 +0000848 onuID uint32, uniID uint32, tpID uint32, increment bool) error {
849 meterInfo, err := rsrcMgr.GetMeterInfoForOnu(ctx, Direction, onuID, uniID, tpID)
Girish Gowdra82c80982021-03-26 16:22:02 -0700850 if err != nil {
851 return err
852 } else if meterInfo == nil {
853 // If we are increasing the reference count, we expect the meter information to be present on KV store.
854 // But if decrementing the reference count, the meter is possibly already cleared from KV store. Just log warn but do not return error.
855 if increment {
yasin saplibddc2d72022-02-08 13:10:17 +0000856 logger.Errorf(ctx, "error-fetching-meter-info-for-intf-%d-onu-%d-uni-%d-tp-id-%d-direction-%s", rsrcMgr.PonIntfID, onuID, uniID, tpID, Direction)
857 return fmt.Errorf("error-fetching-meter-info-for-intf-%d-onu-%d-uni-%d-tp-id-%d-direction-%s", rsrcMgr.PonIntfID, onuID, uniID, tpID, Direction)
Girish Gowdra82c80982021-03-26 16:22:02 -0700858 }
859 logger.Warnw(ctx, "meter is already cleared",
yasin saplibddc2d72022-02-08 13:10:17 +0000860 log.Fields{"intfID": rsrcMgr.PonIntfID, "onuID": onuID, "uniID": uniID, "direction": Direction, "increment": increment})
Girish Gowdra82c80982021-03-26 16:22:02 -0700861 return nil
Girish Gowdraa482f272021-03-24 23:04:19 -0700862 }
Girish Gowdra82c80982021-03-26 16:22:02 -0700863
Girish Gowdraa482f272021-03-24 23:04:19 -0700864 if increment {
865 meterInfo.RefCnt++
866 } else {
867 meterInfo.RefCnt--
Girish Gowdraa482f272021-03-24 23:04:19 -0700868 }
yasin saplibddc2d72022-02-08 13:10:17 +0000869 if err := rsrcMgr.StoreMeterInfoForOnu(ctx, Direction, onuID, uniID, tpID, meterInfo); err != nil {
Girish Gowdraa482f272021-03-24 23:04:19 -0700870 return err
871 }
872 return nil
873}
874
875// RemoveMeterInfoForOnu deletes the meter id from the kV-Store for the given onu based on the path
Gamze Abakafee36392019-10-03 11:17:24 +0000876// This path is formed as the following: <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
yasin saplibddc2d72022-02-08 13:10:17 +0000877func (rsrcMgr *OpenOltResourceMgr) RemoveMeterInfoForOnu(ctx context.Context, Direction string, onuID uint32,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700878 uniID uint32, tpID uint32) error {
yasin saplibddc2d72022-02-08 13:10:17 +0000879 Path := fmt.Sprintf(MeterIDPathSuffix, rsrcMgr.PonIntfID, onuID, uniID, tpID, Direction)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700880
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700881 if err := rsrcMgr.KVStore.Delete(ctx, Path); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000882 logger.Errorf(ctx, "Failed to delete meter id %s from kvstore ", Path)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400883 return err
884 }
Gamze Abaka745ccb72021-11-18 11:29:58 +0000885
886 // update cache
887 rsrcMgr.meterInfoForOnuLock.Lock()
888 delete(rsrcMgr.meterInfoForOnu, Path)
889 rsrcMgr.meterInfoForOnuLock.Unlock()
Manikkaraj kb1d51442019-07-23 10:41:02 -0400890 return nil
891}
salmansiddiqui7ac62132019-08-22 03:58:50 +0000892
Joey Armstrong3f0e2422023-07-05 18:25:41 -0400893// AddGemToOnuGemInfo adds gemport to onugem info kvstore and also local cache
yasin saplibddc2d72022-02-08 13:10:17 +0000894func (rsrcMgr *OpenOltResourceMgr) AddGemToOnuGemInfo(ctx context.Context, onuID uint32, gemPort uint32) error {
895 onugem, err := rsrcMgr.GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700896 if err != nil || onugem == nil || onugem.SerialNumber == "" {
yasin saplibddc2d72022-02-08 13:10:17 +0000897 logger.Errorf(ctx, "failed to get onuifo for intfid %d", rsrcMgr.PonIntfID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530898 return err
899 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700900 if onugem.OnuID == onuID {
901 for _, gem := range onugem.GemPorts {
902 if gem == gemPort {
903 logger.Debugw(ctx, "Gem already present in onugem info, skpping addition", log.Fields{"gem": gem})
904 return nil
905 }
906 }
907 logger.Debugw(ctx, "Added gem to onugem info", log.Fields{"gem": gemPort})
908 onugem.GemPorts = append(onugem.GemPorts, gemPort)
909 } else {
yasin saplibddc2d72022-02-08 13:10:17 +0000910 logger.Errorw(ctx, "onu id in OnuGemInfo does not match", log.Fields{"onuID": onuID, "ponIf": rsrcMgr.PonIntfID, "onuGemInfoOnuID": onugem.OnuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700911 return fmt.Errorf("onu-id-in-OnuGemInfo-does-not-match-%v", onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530912 }
913
yasin saplibddc2d72022-02-08 13:10:17 +0000914 err = rsrcMgr.AddOnuGemInfo(ctx, onuID, *onugem)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530915 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000916 logger.Error(ctx, "Failed to add onugem to kv store")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530917 return err
918 }
919 return err
920}
921
Joey Armstrong3f0e2422023-07-05 18:25:41 -0400922// RemoveGemFromOnuGemInfo removes gemport from onugem info on kvstore and also local cache
yasin saplibddc2d72022-02-08 13:10:17 +0000923func (rsrcMgr *OpenOltResourceMgr) RemoveGemFromOnuGemInfo(ctx context.Context, onuID uint32, gemPort uint32) error {
924 onugem, err := rsrcMgr.GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700925 if err != nil || onugem == nil || onugem.SerialNumber == "" {
yasin saplibddc2d72022-02-08 13:10:17 +0000926 logger.Errorf(ctx, "failed to get onuifo for intfid %d", rsrcMgr.PonIntfID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700927 return err
928 }
929 updated := false
930 if onugem.OnuID == onuID {
931 for i, gem := range onugem.GemPorts {
932 if gem == gemPort {
933 logger.Debugw(ctx, "Gem found, removing from onu gem info", log.Fields{"gem": gem})
934 onugem.GemPorts = append(onugem.GemPorts[:i], onugem.GemPorts[i+1:]...)
935 updated = true
936 break
937 }
938 }
939 } else {
yasin saplibddc2d72022-02-08 13:10:17 +0000940 logger.Errorw(ctx, "onu id in OnuGemInfo does not match", log.Fields{"onuID": onuID, "ponIf": rsrcMgr.PonIntfID, "onuGemInfoOnuID": onugem.OnuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700941 return fmt.Errorf("onu-id-in-OnuGemInfo-does-not-match-%v", onuID)
942 }
943 if updated {
yasin saplibddc2d72022-02-08 13:10:17 +0000944 err = rsrcMgr.AddOnuGemInfo(ctx, onuID, *onugem)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700945 if err != nil {
946 logger.Error(ctx, "Failed to add onugem to kv store")
947 return err
948 }
949 } else {
950 logger.Debugw(ctx, "Gem port not found in onu gem info", log.Fields{"gem": gemPort})
951 }
952 return nil
953}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530954
Joey Armstrong3f0e2422023-07-05 18:25:41 -0400955// GetOnuGemInfo gets onu gem info from the kvstore per interface
yasin saplibddc2d72022-02-08 13:10:17 +0000956func (rsrcMgr *OpenOltResourceMgr) GetOnuGemInfo(ctx context.Context, onuID uint32) (*OnuGemInfo, error) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700957 var err error
958 var Val []byte
959 var onugem OnuGemInfo
960
yasin saplibddc2d72022-02-08 13:10:17 +0000961 path := fmt.Sprintf(OnuGemInfoPath, rsrcMgr.PonIntfID, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700962
963 rsrcMgr.onuGemInfoLock.RLock()
964 val, ok := rsrcMgr.onuGemInfo[path]
965 rsrcMgr.onuGemInfoLock.RUnlock()
966 if ok {
967 return val, nil
968 }
969 value, err := rsrcMgr.KVStore.Get(ctx, path)
970 if err != nil {
971 logger.Errorw(ctx, "Failed to get from kv store", log.Fields{"path": path})
972 return nil, err
973 } else if value == nil {
974 logger.Debug(ctx, "No onuinfo for path", log.Fields{"path": path})
975 return nil, nil // returning nil as this could happen if there are no onus for the interface yet
976 }
977 if Val, err = kvstore.ToByte(value.Value); err != nil {
978 logger.Error(ctx, "Failed to convert to byte array")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530979 return nil, err
980 }
981
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700982 if err = json.Unmarshal(Val, &onugem); err != nil {
983 logger.Error(ctx, "Failed to unmarshall")
984 return nil, err
985 }
986 logger.Debugw(ctx, "found onugem info from path", log.Fields{"path": path, "onuGemInfo": onugem})
987 rsrcMgr.onuGemInfoLock.Lock()
988 rsrcMgr.onuGemInfo[path] = &onugem
989 rsrcMgr.onuGemInfoLock.Unlock()
990
991 return &onugem, nil
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530992}
993
Joey Armstrong3f0e2422023-07-05 18:25:41 -0400994// AddNewOnuGemInfoToCacheAndKvStore function adds a new onu gem info to cache and kvstore
yasin saplibddc2d72022-02-08 13:10:17 +0000995func (rsrcMgr *OpenOltResourceMgr) AddNewOnuGemInfoToCacheAndKvStore(ctx context.Context, onuID uint32, serialNum string) error {
yasin sapli9e4c5092022-02-01 13:52:33 +0000996
yasin saplibddc2d72022-02-08 13:10:17 +0000997 Path := fmt.Sprintf(OnuGemInfoPath, rsrcMgr.PonIntfID, onuID)
yasin sapli9e4c5092022-02-01 13:52:33 +0000998
999 rsrcMgr.onuGemInfoLock.Lock()
1000 _, ok := rsrcMgr.onuGemInfo[Path]
1001 rsrcMgr.onuGemInfoLock.Unlock()
1002
1003 // If the ONU already exists in onuGemInfo list, nothing to do
1004 if ok {
1005 logger.Debugw(ctx, "onu-id-already-exists-in-cache", log.Fields{"onuID": onuID, "serialNum": serialNum})
1006 return nil
1007 }
1008
yasin saplibddc2d72022-02-08 13:10:17 +00001009 onuGemInfo := OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: rsrcMgr.PonIntfID}
yasin sapli9e4c5092022-02-01 13:52:33 +00001010
yasin saplibddc2d72022-02-08 13:10:17 +00001011 if err := rsrcMgr.AddOnuGemInfo(ctx, onuID, onuGemInfo); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +00001012 return err
1013 }
1014 logger.Infow(ctx, "added-onuinfo",
1015 log.Fields{
yasin saplibddc2d72022-02-08 13:10:17 +00001016 "intf-id": rsrcMgr.PonIntfID,
yasin sapli9e4c5092022-02-01 13:52:33 +00001017 "onu-id": onuID,
1018 "serial-num": serialNum,
1019 "onu": onuGemInfo,
1020 "device-id": rsrcMgr.DeviceID})
1021 return nil
1022}
1023
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001024// AddOnuGemInfo adds onu info on to the kvstore per interface
yasin saplibddc2d72022-02-08 13:10:17 +00001025func (rsrcMgr *OpenOltResourceMgr) AddOnuGemInfo(ctx context.Context, onuID uint32, onuGem OnuGemInfo) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001026
1027 var Value []byte
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301028 var err error
yasin saplibddc2d72022-02-08 13:10:17 +00001029 Path := fmt.Sprintf(OnuGemInfoPath, rsrcMgr.PonIntfID, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301030
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001031 Value, err = json.Marshal(onuGem)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301032 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001033 logger.Error(ctx, "failed to Marshal")
1034 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301035 }
1036
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001037 if err = rsrcMgr.KVStore.Put(ctx, Path, Value); err != nil {
1038 logger.Errorf(ctx, "Failed to update resource %s", Path)
1039 return err
1040 }
yasin sapli9e4c5092022-02-01 13:52:33 +00001041 logger.Debugw(ctx, "added onu gem info to store", log.Fields{"onuGemInfo": onuGem, "Path": Path})
Gamze Abaka745ccb72021-11-18 11:29:58 +00001042
1043 //update cache
1044 rsrcMgr.onuGemInfoLock.Lock()
1045 rsrcMgr.onuGemInfo[Path] = &onuGem
1046 rsrcMgr.onuGemInfoLock.Unlock()
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001047 return err
1048}
1049
1050// DelOnuGemInfo deletes the onugem info from kvstore per ONU
yasin saplibddc2d72022-02-08 13:10:17 +00001051func (rsrcMgr *OpenOltResourceMgr) DelOnuGemInfo(ctx context.Context, onuID uint32) error {
1052 path := fmt.Sprintf(OnuGemInfoPath, rsrcMgr.PonIntfID, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001053
1054 if err := rsrcMgr.KVStore.Delete(ctx, path); err != nil {
1055 logger.Errorf(ctx, "failed to remove resource %s", path)
1056 return err
1057 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001058
1059 //update cache
1060 rsrcMgr.onuGemInfoLock.Lock()
1061 logger.Debugw(ctx, "removing onu gem info", log.Fields{"onuGemInfo": rsrcMgr.onuGemInfo[path]})
1062 delete(rsrcMgr.onuGemInfo, path)
1063 rsrcMgr.onuGemInfoLock.Unlock()
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001064 return nil
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301065}
1066
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001067// DeleteAllOnuGemInfoForIntf deletes all the all onu gem info on the given pon interface
yasin saplibddc2d72022-02-08 13:10:17 +00001068func (rsrcMgr *OpenOltResourceMgr) DeleteAllOnuGemInfoForIntf(ctx context.Context) error {
Girish Gowdra950326e2021-11-05 12:43:24 -07001069
yasin saplibddc2d72022-02-08 13:10:17 +00001070 path := fmt.Sprintf(OnuGemInfoPathPathPrefix, rsrcMgr.PonIntfID)
Girish Gowdra950326e2021-11-05 12:43:24 -07001071
yasin saplibddc2d72022-02-08 13:10:17 +00001072 logger.Debugw(ctx, "delete-all-onu-gem-info-for-pon-intf", log.Fields{"intfID": rsrcMgr.PonIntfID})
Girish Gowdra950326e2021-11-05 12:43:24 -07001073 if err := rsrcMgr.KVStore.DeleteWithPrefix(ctx, path); err != nil {
1074 logger.Errorf(ctx, "failed-to-remove-resource-%s", path)
1075 return err
1076 }
1077
1078 // Reset cache. Normally not necessary as the entire device is getting deleted when this API is invoked.
1079 rsrcMgr.onuGemInfoLock.Lock()
1080 rsrcMgr.onuGemInfo = make(map[string]*OnuGemInfo)
1081 rsrcMgr.onuGemInfoLock.Unlock()
1082 return nil
1083}
1084
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301085// AddUniPortToOnuInfo adds uni port to the onuinfo kvstore. check if the uni is already present if not update the kv store.
yasin saplibddc2d72022-02-08 13:10:17 +00001086func (rsrcMgr *OpenOltResourceMgr) AddUniPortToOnuInfo(ctx context.Context, onuID uint32, portNo uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301087
yasin saplibddc2d72022-02-08 13:10:17 +00001088 onugem, err := rsrcMgr.GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001089 if err != nil || onugem == nil || onugem.SerialNumber == "" {
yasin saplibddc2d72022-02-08 13:10:17 +00001090 logger.Warnf(ctx, "failed to get onuifo for intfid %d", rsrcMgr.PonIntfID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301091 return
1092 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001093
1094 if onugem.OnuID == onuID {
1095 for _, uni := range onugem.UniPorts {
1096 if uni == portNo {
1097 logger.Debugw(ctx, "uni already present in onugem info", log.Fields{"uni": portNo})
1098 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301099 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301100 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001101 onugem.UniPorts = append(onugem.UniPorts, portNo)
1102 } else {
yasin saplibddc2d72022-02-08 13:10:17 +00001103 logger.Warnw(ctx, "onu id mismatch in onu gem info", log.Fields{"intfID": rsrcMgr.PonIntfID, "onuID": onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001104 return
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301105 }
yasin saplibddc2d72022-02-08 13:10:17 +00001106 err = rsrcMgr.AddOnuGemInfo(ctx, onuID, *onugem)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301107 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001108 logger.Errorw(ctx, "Failed to add uni port in onugem to kv store", log.Fields{"uni": portNo})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301109 return
1110 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301111}
1112
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001113// UpdateGemPortForPktIn updates gemport for pkt in path to kvstore, path being intfid, onuid, portno, vlan id, priority bit
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001114func (rsrcMgr *OpenOltResourceMgr) UpdateGemPortForPktIn(ctx context.Context, pktIn PacketInInfoKey, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301115
Girish Gowdra950326e2021-11-05 12:43:24 -07001116 path := fmt.Sprintf(OnuPacketInPath, pktIn.IntfID, pktIn.OnuID, pktIn.LogicalPort, pktIn.VlanID, pktIn.Priority)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001117
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301118 Value, err := json.Marshal(gemPort)
1119 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001120 logger.Error(ctx, "Failed to marshal data")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301121 return
1122 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001123 if err = rsrcMgr.KVStore.Put(ctx, path, Value); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001124 logger.Errorw(ctx, "Failed to put to kvstore", log.Fields{"path": path, "value": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301125 return
1126 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001127
1128 // update cache
1129 rsrcMgr.gemPortForPacketInInfoLock.Lock()
1130 rsrcMgr.gemPortForPacketInInfo[path] = gemPort
1131 rsrcMgr.gemPortForPacketInInfoLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00001132 logger.Debugw(ctx, "added gem packet in successfully", log.Fields{"path": path, "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301133}
1134
Esin Karaman7fb80c22020-07-16 14:23:33 +00001135// GetGemPortFromOnuPktIn gets the gem port from onu pkt in path, path being intfid, onuid, portno, vlan id, priority bit
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001136func (rsrcMgr *OpenOltResourceMgr) GetGemPortFromOnuPktIn(ctx context.Context, packetInInfoKey PacketInInfoKey) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301137
1138 var Val []byte
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301139
Girish Gowdra950326e2021-11-05 12:43:24 -07001140 path := fmt.Sprintf(OnuPacketInPath, packetInInfoKey.IntfID, packetInInfoKey.OnuID, packetInInfoKey.LogicalPort,
Esin Karaman7fb80c22020-07-16 14:23:33 +00001141 packetInInfoKey.VlanID, packetInInfoKey.Priority)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001142 // get from cache
1143 rsrcMgr.gemPortForPacketInInfoLock.RLock()
1144 gemPort, ok := rsrcMgr.gemPortForPacketInInfo[path]
1145 rsrcMgr.gemPortForPacketInInfoLock.RUnlock()
1146 if ok {
1147 logger.Debugw(ctx, "found packein gemport from path", log.Fields{"path": path, "gem": gemPort})
1148 return gemPort, nil
1149 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301150
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001151 value, err := rsrcMgr.KVStore.Get(ctx, path)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301152 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001153 logger.Errorw(ctx, "Failed to get from kv store", log.Fields{"path": path})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301154 return uint32(0), err
1155 } else if value == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001156 logger.Debugw(ctx, "No pkt in gem found", log.Fields{"path": path})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301157 return uint32(0), nil
1158 }
1159
1160 if Val, err = kvstore.ToByte(value.Value); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001161 logger.Error(ctx, "Failed to convert to byte array")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301162 return uint32(0), err
1163 }
1164 if err = json.Unmarshal(Val, &gemPort); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001165 logger.Error(ctx, "Failed to unmarshall")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301166 return uint32(0), err
1167 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001168 logger.Debugw(ctx, "found packein gemport from path", log.Fields{"path": path, "gem": gemPort})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001169 // update cache
1170 rsrcMgr.gemPortForPacketInInfoLock.Lock()
1171 rsrcMgr.gemPortForPacketInInfo[path] = gemPort
1172 rsrcMgr.gemPortForPacketInInfoLock.Unlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301173
1174 return gemPort, nil
1175}
1176
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001177// DeletePacketInGemPortForOnu deletes the packet-in gemport for ONU
yasin saplibddc2d72022-02-08 13:10:17 +00001178func (rsrcMgr *OpenOltResourceMgr) DeletePacketInGemPortForOnu(ctx context.Context, onuID uint32, logicalPort uint32) error {
1179 path := fmt.Sprintf(OnuPacketInPathPrefix, rsrcMgr.PonIntfID, onuID, logicalPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001180 value, err := rsrcMgr.KVStore.List(ctx, path)
Esin Karaman7fb80c22020-07-16 14:23:33 +00001181 if err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001182 logger.Errorf(ctx, "failed-to-read-value-from-path-%s", path)
1183 return errors.New("failed-to-read-value-from-path-" + path)
Esin Karaman7fb80c22020-07-16 14:23:33 +00001184 }
Esin Karaman7fb80c22020-07-16 14:23:33 +00001185
Gamze Abaka745ccb72021-11-18 11:29:58 +00001186 logger.Debugw(ctx, "delete-packetin-gem-port", log.Fields{"realPath": path})
1187 if err := rsrcMgr.KVStore.DeleteWithPrefix(ctx, path); err != nil {
1188 logger.Errorf(ctx, "failed-to-remove-resource-%s", path)
1189 return err
1190 }
1191
Esin Karaman7fb80c22020-07-16 14:23:33 +00001192 //remove them one by one
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001193 for key := range value {
serkant.uluderya4f5ed592020-12-17 20:57:59 +03001194 // Remove the PathPrefix from the path on KV key.
Girish Gowdra950326e2021-11-05 12:43:24 -07001195 // gemPortForPacketInInfo cache uses OnuPacketInPath as the key
serkant.uluderya4f5ed592020-12-17 20:57:59 +03001196 stringToBeReplaced := rsrcMgr.KVStore.PathPrefix + "/"
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001197 replacedWith := ""
1198 key = strings.Replace(key, stringToBeReplaced, replacedWith, 1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001199 // update cache
1200 rsrcMgr.gemPortForPacketInInfoLock.Lock()
1201 delete(rsrcMgr.gemPortForPacketInInfo, key)
1202 rsrcMgr.gemPortForPacketInInfoLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001203
serkant.uluderya4f5ed592020-12-17 20:57:59 +03001204 logger.Debugw(ctx, "removed-key-from-packetin-gem-port-cache", log.Fields{"key": key, "cache-len": len(rsrcMgr.gemPortForPacketInInfo)})
1205 }
1206
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301207 return nil
1208}
1209
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001210// GetFlowIDsForGem gets the list of FlowIDs for the given gemport
yasin saplibddc2d72022-02-08 13:10:17 +00001211func (rsrcMgr *OpenOltResourceMgr) GetFlowIDsForGem(ctx context.Context, gem uint32) ([]uint64, error) {
1212 path := fmt.Sprintf(FlowIDsForGem, rsrcMgr.PonIntfID, gem)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001213
1214 // get from cache
1215 rsrcMgr.flowIDsForGemLock.RLock()
1216 flowIDs, ok := rsrcMgr.flowIDsForGem[gem]
1217 rsrcMgr.flowIDsForGemLock.RUnlock()
1218 if ok {
1219 return flowIDs, nil
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301220 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301221
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001222 value, err := rsrcMgr.KVStore.Get(ctx, path)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301223 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001224 logger.Errorw(ctx, "Failed to get from kv store", log.Fields{"path": path})
1225 return nil, err
yasin saplid0566272021-12-21 09:10:30 +00001226 } else if value == nil || value.Value == nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001227 logger.Debug(ctx, "no flow-ids found", log.Fields{"path": path})
1228 return nil, nil
1229 }
1230 Val, err := kvstore.ToByte(value.Value)
1231 if err != nil {
1232 logger.Error(ctx, "Failed to convert to byte array")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301233 return nil, err
1234 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301235
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001236 if err = json.Unmarshal(Val, &flowIDs); err != nil {
1237 logger.Error(ctx, "Failed to unmarshall")
1238 return nil, err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301239 }
1240
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001241 // update cache
1242 rsrcMgr.flowIDsForGemLock.Lock()
1243 rsrcMgr.flowIDsForGem[gem] = flowIDs
1244 rsrcMgr.flowIDsForGemLock.Unlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301245
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001246 return flowIDs, nil
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301247}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301248
yasin sapli9e4c5092022-02-01 13:52:33 +00001249// IsGemPortUsedByAnotherFlow returns true if given gem is used by another flow
Girish Gowdrab4c33302022-03-18 15:07:38 -07001250func (rsrcMgr *OpenOltResourceMgr) IsGemPortUsedByAnotherFlow(ctx context.Context, gemPortID uint32, flowID uint64) (bool, error) {
1251 flowIDList, err := rsrcMgr.GetFlowIDsForGem(ctx, gemPortID)
1252 if err != nil {
1253 return false, err
1254 }
yasin sapli9e4c5092022-02-01 13:52:33 +00001255 for _, id := range flowIDList {
1256 if flowID != id {
Girish Gowdrab4c33302022-03-18 15:07:38 -07001257 return true, nil
yasin sapli9e4c5092022-02-01 13:52:33 +00001258 }
1259 }
Girish Gowdrab4c33302022-03-18 15:07:38 -07001260 return false, nil
yasin sapli9e4c5092022-02-01 13:52:33 +00001261}
1262
1263// RegisterFlowIDForGem updates both cache and KV store for flowIDsForGem map
yasin saplibddc2d72022-02-08 13:10:17 +00001264func (rsrcMgr *OpenOltResourceMgr) RegisterFlowIDForGem(ctx context.Context, gemPortID uint32, flowFromCore *ofp.OfpFlowStats) error {
Girish Gowdrab4c33302022-03-18 15:07:38 -07001265 flowIDs, err := rsrcMgr.GetFlowIDsForGem(ctx, gemPortID)
1266 if err != nil {
1267 return err
yasin sapli9e4c5092022-02-01 13:52:33 +00001268 }
Girish Gowdrab4c33302022-03-18 15:07:38 -07001269
1270 flowIDs = appendUnique64bit(flowIDs, flowFromCore.Id)
yasin sapli9e4c5092022-02-01 13:52:33 +00001271 // update the flowids for a gem to the KVstore
yasin saplibddc2d72022-02-08 13:10:17 +00001272 return rsrcMgr.UpdateFlowIDsForGem(ctx, gemPortID, flowIDs)
yasin sapli9e4c5092022-02-01 13:52:33 +00001273}
1274
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001275// UpdateFlowIDsForGem updates flow id per gemport
yasin saplibddc2d72022-02-08 13:10:17 +00001276func (rsrcMgr *OpenOltResourceMgr) UpdateFlowIDsForGem(ctx context.Context, gem uint32, flowIDs []uint64) error {
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301277 var val []byte
yasin saplibddc2d72022-02-08 13:10:17 +00001278 path := fmt.Sprintf(FlowIDsForGem, rsrcMgr.PonIntfID, gem)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301279
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001280 if flowIDs == nil {
Girish Gowdra950326e2021-11-05 12:43:24 -07001281 if err := rsrcMgr.KVStore.Delete(ctx, path); err != nil {
1282 logger.Errorw(ctx, "Failed to delete from kvstore", log.Fields{"err": err, "path": path})
1283 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001284 return nil
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301285 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001286 val, err := json.Marshal(flowIDs)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301287 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001288 logger.Error(ctx, "Failed to marshal data", log.Fields{"err": err})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301289 return err
1290 }
Girish Gowdrab77ded92020-04-08 11:45:05 -07001291
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001292 if err = rsrcMgr.KVStore.Put(ctx, path, val); err != nil {
1293 logger.Errorw(ctx, "Failed to put to kvstore", log.Fields{"err": err, "path": path, "value": val})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301294 return err
1295 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001296 logger.Debugw(ctx, "added flowid list for gem to kv successfully", log.Fields{"path": path, "flowidlist": flowIDs})
Gamze Abaka745ccb72021-11-18 11:29:58 +00001297
1298 // update cache
1299 rsrcMgr.flowIDsForGemLock.Lock()
1300 rsrcMgr.flowIDsForGem[gem] = flowIDs
1301 rsrcMgr.flowIDsForGemLock.Unlock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05301302 return nil
1303}
1304
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001305// DeleteFlowIDsForGem deletes the flowID list entry per gem from kvstore.
yasin saplibddc2d72022-02-08 13:10:17 +00001306func (rsrcMgr *OpenOltResourceMgr) DeleteFlowIDsForGem(ctx context.Context, gem uint32) error {
1307 path := fmt.Sprintf(FlowIDsForGem, rsrcMgr.PonIntfID, gem)
Gamze Abaka745ccb72021-11-18 11:29:58 +00001308 if err := rsrcMgr.KVStore.Delete(ctx, path); err != nil {
1309 logger.Errorw(ctx, "Failed to delete from kvstore", log.Fields{"err": err, "path": path})
1310 return err
1311 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001312 // update cache
1313 rsrcMgr.flowIDsForGemLock.Lock()
1314 delete(rsrcMgr.flowIDsForGem, gem)
1315 rsrcMgr.flowIDsForGemLock.Unlock()
Gamze Abaka745ccb72021-11-18 11:29:58 +00001316 return nil
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301317}
Esin Karamanccb714b2019-11-29 15:02:06 +00001318
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001319// DeleteAllFlowIDsForGemForIntf deletes all the flow ids associated for all the gems on the given pon interface
yasin saplibddc2d72022-02-08 13:10:17 +00001320func (rsrcMgr *OpenOltResourceMgr) DeleteAllFlowIDsForGemForIntf(ctx context.Context) error {
1321 path := fmt.Sprintf(FlowIDsForGemPathPrefix, rsrcMgr.PonIntfID)
Girish Gowdra950326e2021-11-05 12:43:24 -07001322
yasin saplibddc2d72022-02-08 13:10:17 +00001323 logger.Debugw(ctx, "delete-flow-ids-for-gem-for-pon-intf", log.Fields{"intfID": rsrcMgr.PonIntfID})
Girish Gowdra950326e2021-11-05 12:43:24 -07001324 if err := rsrcMgr.KVStore.DeleteWithPrefix(ctx, path); err != nil {
1325 logger.Errorf(ctx, "failed-to-remove-resource-%s", path)
1326 return err
1327 }
1328
1329 // Reset cache. Normally not necessary as the entire device is getting deleted when this API is invoked.
1330 rsrcMgr.flowIDsForGemLock.Lock()
1331 rsrcMgr.flowIDsForGem = make(map[uint32][]uint64)
1332 rsrcMgr.flowIDsForGemLock.Unlock()
1333 return nil
1334}
1335
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001336// GetMcastQueuePerInterfaceMap gets multicast queue info per pon interface
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001337func (rsrcMgr *OpenOltResourceMgr) GetMcastQueuePerInterfaceMap(ctx context.Context) (map[uint32][]uint32, error) {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001338 path := McastQueuesForIntf
Esin Karamanccb714b2019-11-29 15:02:06 +00001339 var val []byte
1340
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001341 rsrcMgr.mcastQueueForIntfLock.RLock()
1342 if rsrcMgr.mcastQueueForIntfLoadedFromKvStore {
1343 rsrcMgr.mcastQueueForIntfLock.RUnlock()
1344 return rsrcMgr.mcastQueueForIntf, nil
1345 }
1346 rsrcMgr.mcastQueueForIntfLock.RUnlock()
1347
1348 kvPair, err := rsrcMgr.KVStore.Get(ctx, path)
Esin Karamanccb714b2019-11-29 15:02:06 +00001349 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001350 logger.Error(ctx, "failed to get data from kv store")
Esin Karamanccb714b2019-11-29 15:02:06 +00001351 return nil, err
1352 }
1353 if kvPair != nil && kvPair.Value != nil {
1354 if val, err = kvstore.ToByte(kvPair.Value); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001355 logger.Error(ctx, "Failed to convert to byte array ", log.Fields{"err": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00001356 return nil, err
1357 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001358 rsrcMgr.mcastQueueForIntfLock.Lock()
1359 defer rsrcMgr.mcastQueueForIntfLock.Unlock()
1360 if err = json.Unmarshal(val, &rsrcMgr.mcastQueueForIntf); err != nil {
1361 logger.Error(ctx, "Failed to unmarshall ", log.Fields{"err": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00001362 return nil, err
1363 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001364 rsrcMgr.mcastQueueForIntfLoadedFromKvStore = true
Esin Karamanccb714b2019-11-29 15:02:06 +00001365 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001366 return rsrcMgr.mcastQueueForIntf, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00001367}
1368
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001369// AddMcastQueueForIntf adds multicast queue for pon interface
yasin saplibddc2d72022-02-08 13:10:17 +00001370func (rsrcMgr *OpenOltResourceMgr) AddMcastQueueForIntf(ctx context.Context, gem uint32, servicePriority uint32) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00001371 var val []byte
Kent Hagermane6ff1012020-07-14 15:07:53 -04001372 path := McastQueuesForIntf
Esin Karamanccb714b2019-11-29 15:02:06 +00001373
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001374 // Load local cache from kv store the first time
1375 rsrcMgr.mcastQueueForIntfLock.RLock()
1376 if !rsrcMgr.mcastQueueForIntfLoadedFromKvStore {
1377 rsrcMgr.mcastQueueForIntfLock.RUnlock()
1378 _, err := rsrcMgr.GetMcastQueuePerInterfaceMap(ctx)
1379 if err != nil {
yasin saplibddc2d72022-02-08 13:10:17 +00001380 logger.Errorw(ctx, "Failed to get multicast queue info for interface", log.Fields{"err": err, "intf": rsrcMgr.PonIntfID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001381 return err
1382 }
1383 } else {
1384 rsrcMgr.mcastQueueForIntfLock.RUnlock()
1385 }
1386
1387 // Update KV store
1388 rsrcMgr.mcastQueueForIntfLock.Lock()
yasin saplibddc2d72022-02-08 13:10:17 +00001389 rsrcMgr.mcastQueueForIntf[rsrcMgr.PonIntfID] = []uint32{gem, servicePriority}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001390 val, err := json.Marshal(rsrcMgr.mcastQueueForIntf)
Esin Karamanccb714b2019-11-29 15:02:06 +00001391 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001392 rsrcMgr.mcastQueueForIntfLock.Unlock()
1393 logger.Errorw(ctx, "Failed to marshal data", log.Fields{"err": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00001394 return err
1395 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001396 rsrcMgr.mcastQueueForIntfLock.Unlock()
1397
1398 if err = rsrcMgr.KVStore.Put(ctx, path, val); err != nil {
1399 logger.Errorw(ctx, "Failed to put to kvstore", log.Fields{"err": err, "path": path, "value": val})
Esin Karamanccb714b2019-11-29 15:02:06 +00001400 return err
1401 }
yasin saplibddc2d72022-02-08 13:10:17 +00001402 logger.Debugw(ctx, "added multicast queue info to KV store successfully", log.Fields{"path": path, "interfaceId": rsrcMgr.PonIntfID, "gem": gem, "svcPrior": servicePriority})
Esin Karamanccb714b2019-11-29 15:02:06 +00001403 return nil
1404}
1405
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001406// DeleteMcastQueueForIntf deletes multicast queue info for the current pon interface from kvstore
Gustavo Silva41af9122022-10-11 11:05:13 -03001407func (rsrcMgr *OpenOltResourceMgr) DeleteMcastQueueForIntf(ctx context.Context) error {
Girish Gowdraf3728b12022-02-02 21:46:51 -08001408 path := McastQueuesForIntf
1409
1410 if err := rsrcMgr.KVStore.Delete(ctx, path); err != nil {
1411 logger.Errorw(ctx, "Failed to delete multicast queue info from kvstore", log.Fields{"err": err, "interfaceId": rsrcMgr.PonIntfID})
Gustavo Silva41af9122022-10-11 11:05:13 -03001412 return err
Girish Gowdraf3728b12022-02-02 21:46:51 -08001413 }
1414 logger.Debugw(ctx, "deleted multicast queue info from KV store successfully", log.Fields{"interfaceId": rsrcMgr.PonIntfID})
Gustavo Silva41af9122022-10-11 11:05:13 -03001415 return nil
Girish Gowdraf3728b12022-02-02 21:46:51 -08001416}
1417
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001418// AddFlowGroupToKVStore adds flow group into KV store
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001419func (rsrcMgr *OpenOltResourceMgr) AddFlowGroupToKVStore(ctx context.Context, groupEntry *ofp.OfpGroupEntry, cached bool) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00001420 var Value []byte
1421 var err error
1422 var path string
1423 if cached {
1424 path = fmt.Sprintf(FlowGroupCached, groupEntry.Desc.GroupId)
1425 } else {
1426 path = fmt.Sprintf(FlowGroup, groupEntry.Desc.GroupId)
1427 }
1428 //build group info object
1429 var outPorts []uint32
1430 for _, ofBucket := range groupEntry.Desc.Buckets {
1431 for _, ofAction := range ofBucket.Actions {
1432 if ofAction.Type == ofp.OfpActionType_OFPAT_OUTPUT {
1433 outPorts = append(outPorts, ofAction.GetOutput().Port)
1434 }
1435 }
1436 }
1437 groupInfo := GroupInfo{
1438 GroupID: groupEntry.Desc.GroupId,
1439 OutPorts: outPorts,
1440 }
1441
1442 Value, err = json.Marshal(groupInfo)
1443
1444 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001445 logger.Error(ctx, "failed to Marshal flow group object")
Esin Karamanccb714b2019-11-29 15:02:06 +00001446 return err
1447 }
1448
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001449 if err = rsrcMgr.KVStore.Put(ctx, path, Value); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001450 logger.Errorf(ctx, "Failed to update resource %s", path)
Esin Karamanccb714b2019-11-29 15:02:06 +00001451 return err
1452 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001453
1454 // update cache
1455 rsrcMgr.groupInfoLock.Lock()
1456 rsrcMgr.groupInfo[path] = &groupInfo
1457 rsrcMgr.groupInfoLock.Unlock()
Esin Karamanccb714b2019-11-29 15:02:06 +00001458 return nil
1459}
1460
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001461// RemoveFlowGroupFromKVStore removes flow group from KV store
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001462func (rsrcMgr *OpenOltResourceMgr) RemoveFlowGroupFromKVStore(ctx context.Context, groupID uint32, cached bool) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00001463 var path string
1464 if cached {
1465 path = fmt.Sprintf(FlowGroupCached, groupID)
1466 } else {
1467 path = fmt.Sprintf(FlowGroup, groupID)
1468 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001469
1470 if err := rsrcMgr.KVStore.Delete(ctx, path); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001471 logger.Errorf(ctx, "Failed to remove resource %s due to %s", path, err)
Esin Karamand519bbf2020-07-01 11:16:03 +00001472 return err
Esin Karamanccb714b2019-11-29 15:02:06 +00001473 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001474
1475 // update cache
1476 rsrcMgr.groupInfoLock.Lock()
1477 delete(rsrcMgr.groupInfo, path)
1478 rsrcMgr.groupInfoLock.Unlock()
Esin Karamand519bbf2020-07-01 11:16:03 +00001479 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00001480}
1481
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001482// GetFlowGroupFromKVStore fetches flow group from the KV store. Returns (false, {} error) if any problem occurs during
1483// fetching the data. Returns (true, groupInfo, nil) if the group is fetched successfully.
Esin Karamanccb714b2019-11-29 15:02:06 +00001484// Returns (false, {}, nil) if the group does not exists in the KV store.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001485func (rsrcMgr *OpenOltResourceMgr) GetFlowGroupFromKVStore(ctx context.Context, groupID uint32, cached bool) (bool, GroupInfo, error) {
Esin Karamanccb714b2019-11-29 15:02:06 +00001486 var groupInfo GroupInfo
1487 var path string
1488 if cached {
1489 path = fmt.Sprintf(FlowGroupCached, groupID)
1490 } else {
1491 path = fmt.Sprintf(FlowGroup, groupID)
1492 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001493
1494 // read from cache
1495 rsrcMgr.groupInfoLock.RLock()
1496 gi, ok := rsrcMgr.groupInfo[path]
1497 rsrcMgr.groupInfoLock.RUnlock()
1498 if ok {
1499 return true, *gi, nil
1500 }
1501
1502 kvPair, err := rsrcMgr.KVStore.Get(ctx, path)
Esin Karamanccb714b2019-11-29 15:02:06 +00001503 if err != nil {
1504 return false, groupInfo, err
1505 }
1506 if kvPair != nil && kvPair.Value != nil {
1507 Val, err := kvstore.ToByte(kvPair.Value)
1508 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001509 logger.Errorw(ctx, "Failed to convert flow group into byte array", log.Fields{"err": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00001510 return false, groupInfo, err
1511 }
1512 if err = json.Unmarshal(Val, &groupInfo); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001513 logger.Errorw(ctx, "Failed to unmarshal", log.Fields{"err": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00001514 return false, groupInfo, err
1515 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001516 // update cache
1517 rsrcMgr.groupInfoLock.Lock()
1518 rsrcMgr.groupInfo[path] = &groupInfo
1519 rsrcMgr.groupInfoLock.Unlock()
1520
Esin Karamanccb714b2019-11-29 15:02:06 +00001521 return true, groupInfo, nil
1522 }
1523 return false, groupInfo, nil
1524}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001525
yasin sapli9e4c5092022-02-01 13:52:33 +00001526// GetOnuGemInfoList returns all gems in the onuGemInfo map
1527func (rsrcMgr *OpenOltResourceMgr) GetOnuGemInfoList(ctx context.Context) []OnuGemInfo {
1528 var onuGemInfoLst []OnuGemInfo
1529 rsrcMgr.onuGemInfoLock.RLock()
1530 defer rsrcMgr.onuGemInfoLock.RUnlock()
1531 for _, v := range rsrcMgr.onuGemInfo {
1532 onuGemInfoLst = append(onuGemInfoLst, *v)
1533 }
1534 return onuGemInfoLst
1535}
1536
yasin sapli9e4c5092022-02-01 13:52:33 +00001537func appendUnique64bit(slice []uint64, item uint64) []uint64 {
1538 for _, sliceElement := range slice {
1539 if sliceElement == item {
1540 return slice
1541 }
1542 }
1543 return append(slice, item)
1544}