blob: 0eec4527c84b6dde056d5c967783d41b8445bd62 [file] [log] [blame]
Scott Baker2c1c4822019-10-16 11:02:41 -07001/*
Joey Armstrong9cdee9f2024-01-03 04:56:14 -05002 * Copyright 2019-2024 Open Networking Foundation (ONF) and the ONF Contributors
Scott Baker2c1c4822019-10-16 11:02:41 -07003
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
17package ponresourcemanager
18
19import (
npujar5bf737f2020-01-16 19:35:25 +053020 "context"
Scott Baker2c1c4822019-10-16 11:02:41 -070021 "encoding/base64"
22 "encoding/json"
23 "errors"
24 "fmt"
Neha Sharma130ac6d2020-04-08 08:46:32 +000025 "time"
Scott Baker2c1c4822019-10-16 11:02:41 -070026
serkant.uluderyab38671c2019-11-01 09:35:38 -070027 bitmap "github.com/boljen/go-bitmap"
khenaidoo26721882021-08-11 17:42:52 -040028 "github.com/opencord/voltha-lib-go/v7/pkg/db"
29 "github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
30 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Scott Baker2c1c4822019-10-16 11:02:41 -070031)
32
33const (
34 //Constants to identify resource pool
35 UNI_ID = "UNI_ID"
36 ONU_ID = "ONU_ID"
37 ALLOC_ID = "ALLOC_ID"
38 GEMPORT_ID = "GEMPORT_ID"
39 FLOW_ID = "FLOW_ID"
40
khenaidoo26721882021-08-11 17:42:52 -040041 //Constants for passing command line arguments
Scott Baker2c1c4822019-10-16 11:02:41 -070042 OLT_MODEL_ARG = "--olt_model"
Matteo Scandolo29ff79c2020-11-06 13:03:17 -080043
44 PATH_PREFIX = "%s/resource_manager/{%s}"
Esin Karaman5351fc52020-02-14 07:45:49 +000045
46 /*The path under which configuration data is stored is defined as technology/device agnostic.
47 That means the path does not include any specific technology/device variable. Using technology/device
48 agnostic path also makes northbound applications, that need to write to this path,
49 technology/device agnostic.
50
51 Default kv client of PonResourceManager reads from/writes to PATH_PREFIX defined above.
52 That is why, an additional kv client (named KVStoreForConfig) is defined to read from the config path.
53 */
Matteo Scandolo29ff79c2020-11-06 13:03:17 -080054
55 PATH_PREFIX_FOR_CONFIG = "%s/resource_manager/config"
Scott Baker2c1c4822019-10-16 11:02:41 -070056 /*The resource ranges for a given device model should be placed
57 at 'resource_manager/<technology>/resource_ranges/<olt_model_type>'
58 path on the KV store.
59 If Resource Range parameters are to be read from the external KV store,
60 they are expected to be stored in the following format.
61 Note: All parameters are MANDATORY for now.
62 constants used as keys to reference the resource range parameters from
63 and external KV store.
64 */
65 UNI_ID_START_IDX = "uni_id_start"
66 UNI_ID_END_IDX = "uni_id_end"
67 ONU_ID_START_IDX = "onu_id_start"
68 ONU_ID_END_IDX = "onu_id_end"
69 ONU_ID_SHARED_IDX = "onu_id_shared"
70 ALLOC_ID_START_IDX = "alloc_id_start"
71 ALLOC_ID_END_IDX = "alloc_id_end"
72 ALLOC_ID_SHARED_IDX = "alloc_id_shared"
73 GEMPORT_ID_START_IDX = "gemport_id_start"
74 GEMPORT_ID_END_IDX = "gemport_id_end"
75 GEMPORT_ID_SHARED_IDX = "gemport_id_shared"
76 FLOW_ID_START_IDX = "flow_id_start"
77 FLOW_ID_END_IDX = "flow_id_end"
78 FLOW_ID_SHARED_IDX = "flow_id_shared"
79 NUM_OF_PON_PORT = "pon_ports"
80
81 /*
82 The KV store backend is initialized with a path prefix and we need to
83 provide only the suffix.
84 */
85 PON_RESOURCE_RANGE_CONFIG_PATH = "resource_ranges/%s"
86
87 //resource path suffix
88 //Path on the KV store for storing alloc id ranges and resource pool for a given interface
89 //Format: <device_id>/alloc_id_pool/<pon_intf_id>
90 ALLOC_ID_POOL_PATH = "{%s}/alloc_id_pool/{%d}"
91 //Path on the KV store for storing gemport id ranges and resource pool for a given interface
92 //Format: <device_id>/gemport_id_pool/<pon_intf_id>
93 GEMPORT_ID_POOL_PATH = "{%s}/gemport_id_pool/{%d}"
94 //Path on the KV store for storing onu id ranges and resource pool for a given interface
95 //Format: <device_id>/onu_id_pool/<pon_intf_id>
96 ONU_ID_POOL_PATH = "{%s}/onu_id_pool/{%d}"
97 //Path on the KV store for storing flow id ranges and resource pool for a given interface
98 //Format: <device_id>/flow_id_pool/<pon_intf_id>
99 FLOW_ID_POOL_PATH = "{%s}/flow_id_pool/{%d}"
100
101 //Path on the KV store for storing list of alloc IDs for a given ONU
102 //Format: <device_id>/<(pon_intf_id, onu_id)>/alloc_ids
103 ALLOC_ID_RESOURCE_MAP_PATH = "{%s}/{%s}/alloc_ids"
104
105 //Path on the KV store for storing list of gemport IDs for a given ONU
106 //Format: <device_id>/<(pon_intf_id, onu_id)>/gemport_ids
107 GEMPORT_ID_RESOURCE_MAP_PATH = "{%s}/{%s}/gemport_ids"
108
109 //Path on the KV store for storing list of Flow IDs for a given ONU
110 //Format: <device_id>/<(pon_intf_id, onu_id)>/flow_ids
111 FLOW_ID_RESOURCE_MAP_PATH = "{%s}/{%s}/flow_ids"
112
113 //Flow Id info: Use to store more metadata associated with the flow_id
Serkant Uluderya198de902020-11-16 20:29:17 +0300114 FLOW_ID_INFO_PATH_PREFIX = "{%s}/flow_id_info"
115 //Format: <device_id>/flow_id_info/<(pon_intf_id, onu_id)>
116 FLOW_ID_INFO_PATH_INTF_ONU_PREFIX = "{%s}/flow_id_info/{%s}"
117 //Format: <device_id>/flow_id_info/<(pon_intf_id, onu_id)><flow_id>
118 FLOW_ID_INFO_PATH = FLOW_ID_INFO_PATH_PREFIX + "/{%s}/{%d}"
Scott Baker2c1c4822019-10-16 11:02:41 -0700119
120 //Constants for internal usage.
121 PON_INTF_ID = "pon_intf_id"
122 START_IDX = "start_idx"
123 END_IDX = "end_idx"
124 POOL = "pool"
125 NUM_OF_PON_INTF = 16
126
Neha Sharma130ac6d2020-04-08 08:46:32 +0000127 KVSTORE_RETRY_TIMEOUT = 5 * time.Second
Esin Karaman5351fc52020-02-14 07:45:49 +0000128 //Path on the KV store for storing reserved gem ports
129 //Format: reserved_gemport_ids
130 RESERVED_GEMPORT_IDS_PATH = "reserved_gemport_ids"
Scott Baker2c1c4822019-10-16 11:02:41 -0700131)
132
133//type ResourceTypeIndex string
134//type ResourceType string
135
136type PONResourceManager struct {
137 //Implements APIs to initialize/allocate/release alloc/gemport/onu IDs.
Esin Karaman5351fc52020-02-14 07:45:49 +0000138 Technology string
139 DeviceType string
140 DeviceID string
serkant.uluderya2f2855e2021-01-30 12:43:40 +0300141 Backend string // ETCD only currently
Neha Sharmadd9af392020-04-28 09:03:57 +0000142 Address string // address of the KV store
Esin Karaman5351fc52020-02-14 07:45:49 +0000143 OLTModel string
144 KVStore *db.Backend
145 KVStoreForConfig *db.Backend
Scott Baker2c1c4822019-10-16 11:02:41 -0700146
147 // Below attribute, pon_resource_ranges, should be initialized
148 // by reading from KV store.
149 PonResourceRanges map[string]interface{}
150 SharedResourceMgrs map[string]*PONResourceManager
151 SharedIdxByType map[string]string
152 IntfIDs []uint32 // list of pon interface IDs
153 Globalorlocal string
154}
155
Neha Sharma94f16a92020-06-26 04:17:55 +0000156func newKVClient(ctx context.Context, storeType string, address string, timeout time.Duration) (kvstore.Client, error) {
157 logger.Infow(ctx, "kv-store-type", log.Fields{"store": storeType})
Scott Baker2c1c4822019-10-16 11:02:41 -0700158 switch storeType {
Scott Baker2c1c4822019-10-16 11:02:41 -0700159 case "etcd":
Neha Sharma94f16a92020-06-26 04:17:55 +0000160 return kvstore.NewEtcdClient(ctx, address, timeout, log.WarnLevel)
serkant.uluderyae5afeff2021-02-23 18:00:23 +0300161 case "redis":
162 return kvstore.NewRedisClient(address, timeout, false)
163 case "redis-sentinel":
164 return kvstore.NewRedisClient(address, timeout, true)
Scott Baker2c1c4822019-10-16 11:02:41 -0700165 }
166 return nil, errors.New("unsupported-kv-store")
167}
168
Matteo Scandolo29ff79c2020-11-06 13:03:17 -0800169func SetKVClient(ctx context.Context, Technology string, Backend string, Addr string, configClient bool, basePathKvStore string) *db.Backend {
Scott Baker2c1c4822019-10-16 11:02:41 -0700170 // TODO : Make sure direct call to NewBackend is working fine with backend , currently there is some
171 // issue between kv store and backend , core is not calling NewBackend directly
Neha Sharma94f16a92020-06-26 04:17:55 +0000172 kvClient, err := newKVClient(ctx, Backend, Addr, KVSTORE_RETRY_TIMEOUT)
Scott Baker2c1c4822019-10-16 11:02:41 -0700173 if err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000174 logger.Fatalw(ctx, "Failed to init KV client\n", log.Fields{"err": err})
Scott Baker2c1c4822019-10-16 11:02:41 -0700175 return nil
176 }
Esin Karaman5351fc52020-02-14 07:45:49 +0000177
178 var pathPrefix string
179 if configClient {
Matteo Scandolo29ff79c2020-11-06 13:03:17 -0800180 pathPrefix = fmt.Sprintf(PATH_PREFIX_FOR_CONFIG, basePathKvStore)
Esin Karaman5351fc52020-02-14 07:45:49 +0000181 } else {
Matteo Scandolo29ff79c2020-11-06 13:03:17 -0800182 pathPrefix = fmt.Sprintf(PATH_PREFIX, basePathKvStore, Technology)
Esin Karaman5351fc52020-02-14 07:45:49 +0000183 }
184
sbarbari1e3e29c2019-11-05 10:06:50 -0500185 kvbackend := &db.Backend{
Scott Baker2c1c4822019-10-16 11:02:41 -0700186 Client: kvClient,
187 StoreType: Backend,
Neha Sharmadd9af392020-04-28 09:03:57 +0000188 Address: Addr,
Scott Baker2c1c4822019-10-16 11:02:41 -0700189 Timeout: KVSTORE_RETRY_TIMEOUT,
Esin Karaman5351fc52020-02-14 07:45:49 +0000190 PathPrefix: pathPrefix}
Scott Baker2c1c4822019-10-16 11:02:41 -0700191
192 return kvbackend
193}
194
Holger Hildebrandt40bd2672023-02-10 08:14:26 +0000195func (PONRMgr *PONResourceManager) CloseKVClient(ctx context.Context) {
196 if PONRMgr.KVStore != nil {
197 PONRMgr.KVStore.Client.Close(ctx)
198 PONRMgr.KVStore = nil
199 }
200 if PONRMgr.KVStoreForConfig != nil {
201 PONRMgr.KVStoreForConfig.Client.Close(ctx)
202 PONRMgr.KVStoreForConfig = nil
203 }
204}
205
Scott Baker2c1c4822019-10-16 11:02:41 -0700206// NewPONResourceManager creates a new PON resource manager.
Matteo Scandolo29ff79c2020-11-06 13:03:17 -0800207func NewPONResourceManager(ctx context.Context, Technology string, DeviceType string, DeviceID string, Backend string, Address string, basePathKvStore string) (*PONResourceManager, error) {
Scott Baker2c1c4822019-10-16 11:02:41 -0700208 var PONMgr PONResourceManager
209 PONMgr.Technology = Technology
210 PONMgr.DeviceType = DeviceType
211 PONMgr.DeviceID = DeviceID
212 PONMgr.Backend = Backend
Neha Sharmadd9af392020-04-28 09:03:57 +0000213 PONMgr.Address = Address
Matteo Scandolo29ff79c2020-11-06 13:03:17 -0800214 PONMgr.KVStore = SetKVClient(ctx, Technology, Backend, Address, false, basePathKvStore)
Scott Baker2c1c4822019-10-16 11:02:41 -0700215 if PONMgr.KVStore == nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000216 logger.Error(ctx, "KV Client initilization failed")
pnalmas37560752025-01-11 22:05:35 +0530217 return nil, errors.New("failed to init KV client")
Scott Baker2c1c4822019-10-16 11:02:41 -0700218 }
Esin Karaman5351fc52020-02-14 07:45:49 +0000219 // init kv client to read from the config path
Matteo Scandolo29ff79c2020-11-06 13:03:17 -0800220 PONMgr.KVStoreForConfig = SetKVClient(ctx, Technology, Backend, Address, true, basePathKvStore)
Esin Karaman5351fc52020-02-14 07:45:49 +0000221 if PONMgr.KVStoreForConfig == nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000222 logger.Error(ctx, "KV Config Client initilization failed")
pnalmas37560752025-01-11 22:05:35 +0530223 return nil, errors.New("failed to init KV Config client")
Esin Karaman5351fc52020-02-14 07:45:49 +0000224 }
Girish Gowdrad72fef42021-07-22 16:30:58 -0700225
Scott Baker2c1c4822019-10-16 11:02:41 -0700226 PONMgr.PonResourceRanges = make(map[string]interface{})
227 PONMgr.SharedResourceMgrs = make(map[string]*PONResourceManager)
228 PONMgr.SharedIdxByType = make(map[string]string)
229 PONMgr.SharedIdxByType[ONU_ID] = ONU_ID_SHARED_IDX
230 PONMgr.SharedIdxByType[ALLOC_ID] = ALLOC_ID_SHARED_IDX
231 PONMgr.SharedIdxByType[GEMPORT_ID] = GEMPORT_ID_SHARED_IDX
232 PONMgr.SharedIdxByType[FLOW_ID] = FLOW_ID_SHARED_IDX
233 PONMgr.IntfIDs = make([]uint32, NUM_OF_PON_INTF)
234 PONMgr.OLTModel = DeviceType
235 return &PONMgr, nil
236}
237
238/*
239 Initialize PON resource ranges with config fetched from kv store.
240 return boolean: True if PON resource ranges initialized else false
241 Try to initialize the PON Resource Ranges from KV store based on the
242 OLT model key, if available
243*/
244
npujar5bf737f2020-01-16 19:35:25 +0530245func (PONRMgr *PONResourceManager) InitResourceRangesFromKVStore(ctx context.Context) bool {
Scott Baker2c1c4822019-10-16 11:02:41 -0700246 //Initialize PON resource ranges with config fetched from kv store.
247 //:return boolean: True if PON resource ranges initialized else false
248 // Try to initialize the PON Resource Ranges from KV store based on the
249 // OLT model key, if available
250 if PONRMgr.OLTModel == "" {
Neha Sharma94f16a92020-06-26 04:17:55 +0000251 logger.Error(ctx, "Failed to get OLT model")
Scott Baker2c1c4822019-10-16 11:02:41 -0700252 return false
253 }
254 Path := fmt.Sprintf(PON_RESOURCE_RANGE_CONFIG_PATH, PONRMgr.OLTModel)
255 //get resource from kv store
npujar5bf737f2020-01-16 19:35:25 +0530256 Result, err := PONRMgr.KVStore.Get(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700257 if err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000258 logger.Debugf(ctx, "Error in fetching resource %s from KV strore", Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700259 return false
260 }
261 if Result == nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000262 logger.Debug(ctx, "There may be no resources in the KV store in case of fresh bootup, return true")
Scott Baker2c1c4822019-10-16 11:02:41 -0700263 return false
264 }
265 //update internal ranges from kv ranges. If there are missing
266 // values in the KV profile, continue to use the defaults
267 Value, err := ToByte(Result.Value)
268 if err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000269 logger.Error(ctx, "Failed to convert kvpair to byte string")
Scott Baker2c1c4822019-10-16 11:02:41 -0700270 return false
271 }
272 if err := json.Unmarshal(Value, &PONRMgr.PonResourceRanges); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000273 logger.Error(ctx, "Failed to Unmarshal json byte")
Scott Baker2c1c4822019-10-16 11:02:41 -0700274 return false
275 }
Neha Sharma94f16a92020-06-26 04:17:55 +0000276 logger.Debug(ctx, "Init resource ranges from kvstore success")
Scott Baker2c1c4822019-10-16 11:02:41 -0700277 return true
278}
279
Neha Sharma94f16a92020-06-26 04:17:55 +0000280func (PONRMgr *PONResourceManager) UpdateRanges(ctx context.Context, StartIDx string, StartID uint32, EndIDx string, EndID uint32,
Scott Baker2c1c4822019-10-16 11:02:41 -0700281 SharedIDx string, SharedPoolID uint32, RMgr *PONResourceManager) {
282 /*
283 Update the ranges for all reosurce type in the intermnal maps
284 param: resource type start index
285 param: start ID
286 param: resource type end index
287 param: end ID
288 param: resource type shared index
289 param: shared pool id
290 param: global resource manager
291 */
Neha Sharma94f16a92020-06-26 04:17:55 +0000292 logger.Debugf(ctx, "update ranges for %s, %d", StartIDx, StartID)
Scott Baker2c1c4822019-10-16 11:02:41 -0700293
294 if StartID != 0 {
295 if (PONRMgr.PonResourceRanges[StartIDx] == nil) || (PONRMgr.PonResourceRanges[StartIDx].(uint32) < StartID) {
296 PONRMgr.PonResourceRanges[StartIDx] = StartID
297 }
298 }
299 if EndID != 0 {
300 if (PONRMgr.PonResourceRanges[EndIDx] == nil) || (PONRMgr.PonResourceRanges[EndIDx].(uint32) > EndID) {
301 PONRMgr.PonResourceRanges[EndIDx] = EndID
302 }
303 }
304 //if SharedPoolID != 0 {
305 PONRMgr.PonResourceRanges[SharedIDx] = SharedPoolID
306 //}
307 if RMgr != nil {
308 PONRMgr.SharedResourceMgrs[SharedIDx] = RMgr
309 }
310}
311
Neha Sharma94f16a92020-06-26 04:17:55 +0000312func (PONRMgr *PONResourceManager) InitDefaultPONResourceRanges(ctx context.Context,
313 ONUIDStart uint32,
Scott Baker2c1c4822019-10-16 11:02:41 -0700314 ONUIDEnd uint32,
315 ONUIDSharedPoolID uint32,
316 AllocIDStart uint32,
317 AllocIDEnd uint32,
318 AllocIDSharedPoolID uint32,
319 GEMPortIDStart uint32,
320 GEMPortIDEnd uint32,
321 GEMPortIDSharedPoolID uint32,
322 FlowIDStart uint32,
323 FlowIDEnd uint32,
324 FlowIDSharedPoolID uint32,
325 UNIIDStart uint32,
326 UNIIDEnd uint32,
327 NoOfPONPorts uint32,
328 IntfIDs []uint32) bool {
329
330 /*Initialize default PON resource ranges
331
332 :param onu_id_start_idx: onu id start index
333 :param onu_id_end_idx: onu id end index
334 :param onu_id_shared_pool_id: pool idx for id shared by all intfs or None for no sharing
335 :param alloc_id_start_idx: alloc id start index
336 :param alloc_id_end_idx: alloc id end index
337 :param alloc_id_shared_pool_id: pool idx for alloc id shared by all intfs or None for no sharing
338 :param gemport_id_start_idx: gemport id start index
339 :param gemport_id_end_idx: gemport id end index
340 :param gemport_id_shared_pool_id: pool idx for gemport id shared by all intfs or None for no sharing
341 :param flow_id_start_idx: flow id start index
342 :param flow_id_end_idx: flow id end index
343 :param flow_id_shared_pool_id: pool idx for flow id shared by all intfs or None for no sharing
344 :param num_of_pon_ports: number of PON ports
345 :param intf_ids: interfaces serviced by this manager
346 */
Neha Sharma94f16a92020-06-26 04:17:55 +0000347 PONRMgr.UpdateRanges(ctx, ONU_ID_START_IDX, ONUIDStart, ONU_ID_END_IDX, ONUIDEnd, ONU_ID_SHARED_IDX, ONUIDSharedPoolID, nil)
348 PONRMgr.UpdateRanges(ctx, ALLOC_ID_START_IDX, AllocIDStart, ALLOC_ID_END_IDX, AllocIDEnd, ALLOC_ID_SHARED_IDX, AllocIDSharedPoolID, nil)
349 PONRMgr.UpdateRanges(ctx, GEMPORT_ID_START_IDX, GEMPortIDStart, GEMPORT_ID_END_IDX, GEMPortIDEnd, GEMPORT_ID_SHARED_IDX, GEMPortIDSharedPoolID, nil)
350 PONRMgr.UpdateRanges(ctx, FLOW_ID_START_IDX, FlowIDStart, FLOW_ID_END_IDX, FlowIDEnd, FLOW_ID_SHARED_IDX, FlowIDSharedPoolID, nil)
351 PONRMgr.UpdateRanges(ctx, UNI_ID_START_IDX, UNIIDStart, UNI_ID_END_IDX, UNIIDEnd, "", 0, nil)
352 logger.Debug(ctx, "Initialize default range values")
Scott Baker2c1c4822019-10-16 11:02:41 -0700353 var i uint32
354 if IntfIDs == nil {
355 for i = 0; i < NoOfPONPorts; i++ {
356 PONRMgr.IntfIDs = append(PONRMgr.IntfIDs, i)
357 }
358 } else {
359 PONRMgr.IntfIDs = IntfIDs
360 }
361 return true
362}
363
npujar5bf737f2020-01-16 19:35:25 +0530364func (PONRMgr *PONResourceManager) InitDeviceResourcePool(ctx context.Context) error {
Scott Baker2c1c4822019-10-16 11:02:41 -0700365
366 //Initialize resource pool for all PON ports.
367
Neha Sharma94f16a92020-06-26 04:17:55 +0000368 logger.Debug(ctx, "Init resource ranges")
Scott Baker2c1c4822019-10-16 11:02:41 -0700369
370 var err error
371 for _, Intf := range PONRMgr.IntfIDs {
372 SharedPoolID := PONRMgr.PonResourceRanges[ONU_ID_SHARED_IDX].(uint32)
373 if SharedPoolID != 0 {
374 Intf = SharedPoolID
375 }
npujar5bf737f2020-01-16 19:35:25 +0530376 if err = PONRMgr.InitResourceIDPool(ctx, Intf, ONU_ID,
Scott Baker2c1c4822019-10-16 11:02:41 -0700377 PONRMgr.PonResourceRanges[ONU_ID_START_IDX].(uint32),
378 PONRMgr.PonResourceRanges[ONU_ID_END_IDX].(uint32)); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000379 logger.Error(ctx, "Failed to init ONU ID resource pool")
Scott Baker2c1c4822019-10-16 11:02:41 -0700380 return err
381 }
382 if SharedPoolID != 0 {
383 break
384 }
385 }
386
387 for _, Intf := range PONRMgr.IntfIDs {
388 SharedPoolID := PONRMgr.PonResourceRanges[ALLOC_ID_SHARED_IDX].(uint32)
389 if SharedPoolID != 0 {
390 Intf = SharedPoolID
391 }
npujar5bf737f2020-01-16 19:35:25 +0530392 if err = PONRMgr.InitResourceIDPool(ctx, Intf, ALLOC_ID,
Scott Baker2c1c4822019-10-16 11:02:41 -0700393 PONRMgr.PonResourceRanges[ALLOC_ID_START_IDX].(uint32),
394 PONRMgr.PonResourceRanges[ALLOC_ID_END_IDX].(uint32)); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000395 logger.Error(ctx, "Failed to init ALLOC ID resource pool ")
Scott Baker2c1c4822019-10-16 11:02:41 -0700396 return err
397 }
398 if SharedPoolID != 0 {
399 break
400 }
401 }
402 for _, Intf := range PONRMgr.IntfIDs {
403 SharedPoolID := PONRMgr.PonResourceRanges[GEMPORT_ID_SHARED_IDX].(uint32)
404 if SharedPoolID != 0 {
405 Intf = SharedPoolID
406 }
npujar5bf737f2020-01-16 19:35:25 +0530407 if err = PONRMgr.InitResourceIDPool(ctx, Intf, GEMPORT_ID,
Scott Baker2c1c4822019-10-16 11:02:41 -0700408 PONRMgr.PonResourceRanges[GEMPORT_ID_START_IDX].(uint32),
409 PONRMgr.PonResourceRanges[GEMPORT_ID_END_IDX].(uint32)); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000410 logger.Error(ctx, "Failed to init GEMPORT ID resource pool")
Scott Baker2c1c4822019-10-16 11:02:41 -0700411 return err
412 }
413 if SharedPoolID != 0 {
414 break
415 }
416 }
417
418 for _, Intf := range PONRMgr.IntfIDs {
419 SharedPoolID := PONRMgr.PonResourceRanges[FLOW_ID_SHARED_IDX].(uint32)
420 if SharedPoolID != 0 {
421 Intf = SharedPoolID
422 }
npujar5bf737f2020-01-16 19:35:25 +0530423 if err = PONRMgr.InitResourceIDPool(ctx, Intf, FLOW_ID,
Scott Baker2c1c4822019-10-16 11:02:41 -0700424 PONRMgr.PonResourceRanges[FLOW_ID_START_IDX].(uint32),
425 PONRMgr.PonResourceRanges[FLOW_ID_END_IDX].(uint32)); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000426 logger.Error(ctx, "Failed to init FLOW ID resource pool")
Scott Baker2c1c4822019-10-16 11:02:41 -0700427 return err
428 }
429 if SharedPoolID != 0 {
430 break
431 }
432 }
433 return err
434}
435
Girish Gowdra248971a2021-06-01 15:14:15 -0700436func (PONRMgr *PONResourceManager) InitDeviceResourcePoolForIntf(ctx context.Context, intfID uint32) error {
437
438 logger.Debug(ctx, "Init resource ranges for intf %d", intfID)
439
440 var err error
441
442 if err = PONRMgr.InitResourceIDPool(ctx, intfID, ONU_ID,
443 PONRMgr.PonResourceRanges[ONU_ID_START_IDX].(uint32),
444 PONRMgr.PonResourceRanges[ONU_ID_END_IDX].(uint32)); err != nil {
445 logger.Error(ctx, "Failed to init ONU ID resource pool")
446 return err
447 }
448
449 if err = PONRMgr.InitResourceIDPool(ctx, intfID, ALLOC_ID,
450 PONRMgr.PonResourceRanges[ALLOC_ID_START_IDX].(uint32),
451 PONRMgr.PonResourceRanges[ALLOC_ID_END_IDX].(uint32)); err != nil {
452 logger.Error(ctx, "Failed to init ALLOC ID resource pool ")
453 return err
454 }
455
456 if err = PONRMgr.InitResourceIDPool(ctx, intfID, GEMPORT_ID,
457 PONRMgr.PonResourceRanges[GEMPORT_ID_START_IDX].(uint32),
458 PONRMgr.PonResourceRanges[GEMPORT_ID_END_IDX].(uint32)); err != nil {
459 logger.Error(ctx, "Failed to init GEMPORT ID resource pool")
460 return err
461 }
462
463 if err = PONRMgr.InitResourceIDPool(ctx, intfID, FLOW_ID,
464 PONRMgr.PonResourceRanges[FLOW_ID_START_IDX].(uint32),
465 PONRMgr.PonResourceRanges[FLOW_ID_END_IDX].(uint32)); err != nil {
466 logger.Error(ctx, "Failed to init FLOW ID resource pool")
467 return err
468 }
469
470 return nil
471}
472
npujar5bf737f2020-01-16 19:35:25 +0530473func (PONRMgr *PONResourceManager) ClearDeviceResourcePool(ctx context.Context) error {
Scott Baker2c1c4822019-10-16 11:02:41 -0700474
475 //Clear resource pool for all PON ports.
476
Neha Sharma94f16a92020-06-26 04:17:55 +0000477 logger.Debug(ctx, "Clear resource ranges")
Scott Baker2c1c4822019-10-16 11:02:41 -0700478
479 for _, Intf := range PONRMgr.IntfIDs {
480 SharedPoolID := PONRMgr.PonResourceRanges[ONU_ID_SHARED_IDX].(uint32)
481 if SharedPoolID != 0 {
482 Intf = SharedPoolID
483 }
David K. Bainbridge7c75cac2020-02-19 08:53:46 -0800484 if status := PONRMgr.ClearResourceIDPool(ctx, Intf, ONU_ID); !status {
Neha Sharma94f16a92020-06-26 04:17:55 +0000485 logger.Error(ctx, "Failed to clear ONU ID resource pool")
pnalmas37560752025-01-11 22:05:35 +0530486 return errors.New("failed to clear ONU ID resource pool")
Scott Baker2c1c4822019-10-16 11:02:41 -0700487 }
488 if SharedPoolID != 0 {
489 break
490 }
491 }
492
493 for _, Intf := range PONRMgr.IntfIDs {
494 SharedPoolID := PONRMgr.PonResourceRanges[ALLOC_ID_SHARED_IDX].(uint32)
495 if SharedPoolID != 0 {
496 Intf = SharedPoolID
497 }
David K. Bainbridge7c75cac2020-02-19 08:53:46 -0800498 if status := PONRMgr.ClearResourceIDPool(ctx, Intf, ALLOC_ID); !status {
Neha Sharma94f16a92020-06-26 04:17:55 +0000499 logger.Error(ctx, "Failed to clear ALLOC ID resource pool ")
pnalmas37560752025-01-11 22:05:35 +0530500 return errors.New("failed to clear ALLOC ID resource pool")
Scott Baker2c1c4822019-10-16 11:02:41 -0700501 }
502 if SharedPoolID != 0 {
503 break
504 }
505 }
506 for _, Intf := range PONRMgr.IntfIDs {
507 SharedPoolID := PONRMgr.PonResourceRanges[GEMPORT_ID_SHARED_IDX].(uint32)
508 if SharedPoolID != 0 {
509 Intf = SharedPoolID
510 }
David K. Bainbridge7c75cac2020-02-19 08:53:46 -0800511 if status := PONRMgr.ClearResourceIDPool(ctx, Intf, GEMPORT_ID); !status {
Neha Sharma94f16a92020-06-26 04:17:55 +0000512 logger.Error(ctx, "Failed to clear GEMPORT ID resource pool")
pnalmas37560752025-01-11 22:05:35 +0530513 return errors.New("failed to clear GEMPORT ID resource pool")
Scott Baker2c1c4822019-10-16 11:02:41 -0700514 }
515 if SharedPoolID != 0 {
516 break
517 }
518 }
519
520 for _, Intf := range PONRMgr.IntfIDs {
521 SharedPoolID := PONRMgr.PonResourceRanges[FLOW_ID_SHARED_IDX].(uint32)
522 if SharedPoolID != 0 {
523 Intf = SharedPoolID
524 }
David K. Bainbridge7c75cac2020-02-19 08:53:46 -0800525 if status := PONRMgr.ClearResourceIDPool(ctx, Intf, FLOW_ID); !status {
Neha Sharma94f16a92020-06-26 04:17:55 +0000526 logger.Error(ctx, "Failed to clear FLOW ID resource pool")
pnalmas37560752025-01-11 22:05:35 +0530527 return errors.New("failed to clear FLOW ID resource pool")
Scott Baker2c1c4822019-10-16 11:02:41 -0700528 }
529 if SharedPoolID != 0 {
530 break
531 }
532 }
533 return nil
534}
535
Girish Gowdra248971a2021-06-01 15:14:15 -0700536func (PONRMgr *PONResourceManager) ClearDeviceResourcePoolForIntf(ctx context.Context, intfID uint32) error {
537
538 logger.Debugf(ctx, "Clear resource ranges for intf %d", intfID)
539
540 if status := PONRMgr.ClearResourceIDPool(ctx, intfID, ONU_ID); !status {
541 logger.Error(ctx, "Failed to clear ONU ID resource pool")
pnalmas37560752025-01-11 22:05:35 +0530542 return errors.New("failed to clear ONU ID resource pool")
Girish Gowdra248971a2021-06-01 15:14:15 -0700543 }
544
545 if status := PONRMgr.ClearResourceIDPool(ctx, intfID, ALLOC_ID); !status {
546 logger.Error(ctx, "Failed to clear ALLOC ID resource pool ")
pnalmas37560752025-01-11 22:05:35 +0530547 return errors.New("failed to clear ALLOC ID resource pool")
Girish Gowdra248971a2021-06-01 15:14:15 -0700548 }
549
550 if status := PONRMgr.ClearResourceIDPool(ctx, intfID, GEMPORT_ID); !status {
551 logger.Error(ctx, "Failed to clear GEMPORT ID resource pool")
pnalmas37560752025-01-11 22:05:35 +0530552 return errors.New("failed to clear GEMPORT ID resource pool")
Girish Gowdra248971a2021-06-01 15:14:15 -0700553 }
554
555 if status := PONRMgr.ClearResourceIDPool(ctx, intfID, FLOW_ID); !status {
556 logger.Error(ctx, "Failed to clear FLOW ID resource pool")
pnalmas37560752025-01-11 22:05:35 +0530557 return errors.New("failed to clear FLOW ID resource pool")
Girish Gowdra248971a2021-06-01 15:14:15 -0700558 }
559
560 return nil
561}
562
npujar5bf737f2020-01-16 19:35:25 +0530563func (PONRMgr *PONResourceManager) InitResourceIDPool(ctx context.Context, Intf uint32, ResourceType string, StartID uint32, EndID uint32) error {
Scott Baker2c1c4822019-10-16 11:02:41 -0700564
565 /*Initialize Resource ID pool for a given Resource Type on a given PON Port
566
567 :param pon_intf_id: OLT PON interface id
568 :param resource_type: String to identify type of resource
569 :param start_idx: start index for onu id pool
570 :param end_idx: end index for onu id pool
571 :return boolean: True if resource id pool initialized else false
572 */
573
574 // delegate to the master instance if sharing enabled across instances
575 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
576 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
npujar5bf737f2020-01-16 19:35:25 +0530577 return SharedResourceMgr.InitResourceIDPool(ctx, Intf, ResourceType, StartID, EndID)
Scott Baker2c1c4822019-10-16 11:02:41 -0700578 }
579
Neha Sharma94f16a92020-06-26 04:17:55 +0000580 Path := PONRMgr.GetPath(ctx, Intf, ResourceType)
Scott Baker2c1c4822019-10-16 11:02:41 -0700581 if Path == "" {
Neha Sharma94f16a92020-06-26 04:17:55 +0000582 logger.Errorf(ctx, "Failed to get path for resource type %s", ResourceType)
pnalmas37560752025-01-11 22:05:35 +0530583 return fmt.Errorf("failed to get path for resource type %s", ResourceType)
Scott Baker2c1c4822019-10-16 11:02:41 -0700584 }
585
586 //In case of adapter reboot and reconciliation resource in kv store
587 //checked for its presence if not kv store update happens
npujar5bf737f2020-01-16 19:35:25 +0530588 Res, err := PONRMgr.GetResource(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700589 if (err == nil) && (Res != nil) {
Neha Sharma94f16a92020-06-26 04:17:55 +0000590 logger.Debugf(ctx, "Resource %s already present in store ", Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700591 return nil
592 } else {
Esin Karaman5351fc52020-02-14 07:45:49 +0000593 var excluded []uint32
594 if ResourceType == GEMPORT_ID {
595 //get gem port ids defined in the KV store, if any, and exclude them from the gem port id pool
596 if reservedGemPortIds, defined := PONRMgr.getReservedGemPortIdsFromKVStore(ctx); defined {
597 excluded = reservedGemPortIds
Neha Sharma94f16a92020-06-26 04:17:55 +0000598 logger.Debugw(ctx, "Excluding some ports from GEM port id pool", log.Fields{"excluded gem ports": excluded})
Esin Karaman5351fc52020-02-14 07:45:49 +0000599 }
600 }
Neha Sharma94f16a92020-06-26 04:17:55 +0000601 FormatResult, err := PONRMgr.FormatResource(ctx, Intf, StartID, EndID, excluded)
Scott Baker2c1c4822019-10-16 11:02:41 -0700602 if err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000603 logger.Errorf(ctx, "Failed to format resource")
Scott Baker2c1c4822019-10-16 11:02:41 -0700604 return err
605 }
606 // Add resource as json in kv store.
npujar5bf737f2020-01-16 19:35:25 +0530607 err = PONRMgr.KVStore.Put(ctx, Path, FormatResult)
Scott Baker2c1c4822019-10-16 11:02:41 -0700608 if err == nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000609 logger.Debug(ctx, "Successfuly posted to kv store")
Scott Baker2c1c4822019-10-16 11:02:41 -0700610 return err
611 }
612 }
613
Neha Sharma94f16a92020-06-26 04:17:55 +0000614 logger.Debug(ctx, "Error initializing pool")
Scott Baker2c1c4822019-10-16 11:02:41 -0700615
616 return err
617}
618
Esin Karaman5351fc52020-02-14 07:45:49 +0000619func (PONRMgr *PONResourceManager) getReservedGemPortIdsFromKVStore(ctx context.Context) ([]uint32, bool) {
620 var reservedGemPortIds []uint32
621 // read reserved gem ports from the config path
622 KvPair, err := PONRMgr.KVStoreForConfig.Get(ctx, RESERVED_GEMPORT_IDS_PATH)
623 if err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000624 logger.Errorw(ctx, "Unable to get reserved GEM port ids from the kv store", log.Fields{"err": err})
Esin Karaman5351fc52020-02-14 07:45:49 +0000625 return reservedGemPortIds, false
626 }
627 if KvPair == nil || KvPair.Value == nil {
628 //no reserved gem port defined in the store
629 return reservedGemPortIds, false
630 }
631 Val, err := kvstore.ToByte(KvPair.Value)
632 if err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000633 logger.Errorw(ctx, "Failed to convert reserved gem port ids into byte array", log.Fields{"err": err})
Esin Karaman5351fc52020-02-14 07:45:49 +0000634 return reservedGemPortIds, false
635 }
636 if err = json.Unmarshal(Val, &reservedGemPortIds); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000637 logger.Errorw(ctx, "Failed to unmarshal reservedGemPortIds", log.Fields{"err": err})
Esin Karaman5351fc52020-02-14 07:45:49 +0000638 return reservedGemPortIds, false
639 }
640 return reservedGemPortIds, true
641}
642
Neha Sharma94f16a92020-06-26 04:17:55 +0000643func (PONRMgr *PONResourceManager) FormatResource(ctx context.Context, IntfID uint32, StartIDx uint32, EndIDx uint32,
Esin Karaman5351fc52020-02-14 07:45:49 +0000644 Excluded []uint32) ([]byte, error) {
Scott Baker2c1c4822019-10-16 11:02:41 -0700645 /*
646 Format resource as json.
647 :param pon_intf_id: OLT PON interface id
648 :param start_idx: start index for id pool
649 :param end_idx: end index for id pool
Esin Karaman5351fc52020-02-14 07:45:49 +0000650 :Id values to be Excluded from the pool
Scott Baker2c1c4822019-10-16 11:02:41 -0700651 :return dictionary: resource formatted as map
652 */
653 // Format resource as json to be stored in backend store
654 Resource := make(map[string]interface{})
655 Resource[PON_INTF_ID] = IntfID
656 Resource[START_IDX] = StartIDx
657 Resource[END_IDX] = EndIDx
658 /*
659 Resource pool stored in backend store as binary string.
660 Tracking the resource allocation will be done by setting the bits \
661 in the byte array. The index set will be the resource number allocated.
662 */
663 var TSData *bitmap.Threadsafe
664 if TSData = bitmap.NewTS(int(EndIDx)); TSData == nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000665 logger.Error(ctx, "Failed to create a bitmap")
pnalmas37560752025-01-11 22:05:35 +0530666 return nil, errors.New("failed to create bitmap")
Scott Baker2c1c4822019-10-16 11:02:41 -0700667 }
Esin Karaman5351fc52020-02-14 07:45:49 +0000668 for _, excludedID := range Excluded {
669 if excludedID < StartIDx || excludedID > EndIDx {
Neha Sharma94f16a92020-06-26 04:17:55 +0000670 logger.Warnf(ctx, "Cannot reserve %d. It must be in the range of [%d, %d]", excludedID,
Esin Karaman5351fc52020-02-14 07:45:49 +0000671 StartIDx, EndIDx)
672 continue
673 }
Neha Sharma94f16a92020-06-26 04:17:55 +0000674 PONRMgr.reserveID(ctx, TSData, StartIDx, excludedID)
Esin Karaman5351fc52020-02-14 07:45:49 +0000675 }
Scott Baker2c1c4822019-10-16 11:02:41 -0700676 Resource[POOL] = TSData.Data(false) //we pass false so as the TSData lib api does not do a copy of the data and return
677
678 Value, err := json.Marshal(Resource)
679 if err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000680 logger.Errorf(ctx, "Failed to marshall resource")
Scott Baker2c1c4822019-10-16 11:02:41 -0700681 return nil, err
682 }
683 return Value, err
684}
npujar5bf737f2020-01-16 19:35:25 +0530685func (PONRMgr *PONResourceManager) GetResource(ctx context.Context, Path string) (map[string]interface{}, error) {
Scott Baker2c1c4822019-10-16 11:02:41 -0700686 /*
687 Get resource from kv store.
688
689 :param path: path to get resource
690 :return: resource if resource present in kv store else None
691 */
692 //get resource from kv store
693
694 var Value []byte
695 Result := make(map[string]interface{})
696 var Str string
697
npujar5bf737f2020-01-16 19:35:25 +0530698 Resource, err := PONRMgr.KVStore.Get(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700699 if (err != nil) || (Resource == nil) {
Neha Sharma94f16a92020-06-26 04:17:55 +0000700 logger.Debugf(ctx, "Resource unavailable at %s", Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700701 return nil, err
702 }
703
704 Value, err = ToByte(Resource.Value)
David K. Bainbridge7c75cac2020-02-19 08:53:46 -0800705 if err != nil {
706 return nil, err
707 }
Scott Baker2c1c4822019-10-16 11:02:41 -0700708
709 // decode resource fetched from backend store to dictionary
710 err = json.Unmarshal(Value, &Result)
711 if err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000712 logger.Error(ctx, "Failed to decode resource")
Scott Baker2c1c4822019-10-16 11:02:41 -0700713 return Result, err
714 }
715 /*
716 resource pool in backend store stored as binary string whereas to
717 access the pool to generate/release IDs it need to be converted
718 as BitArray
719 */
720 Str, err = ToString(Result[POOL])
721 if err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000722 logger.Error(ctx, "Failed to conver to kv pair to string")
Scott Baker2c1c4822019-10-16 11:02:41 -0700723 return Result, err
724 }
725 Decode64, _ := base64.StdEncoding.DecodeString(Str)
726 Result[POOL], err = ToByte(Decode64)
727 if err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000728 logger.Error(ctx, "Failed to convert resource pool to byte")
Scott Baker2c1c4822019-10-16 11:02:41 -0700729 return Result, err
730 }
731
732 return Result, err
733}
734
Neha Sharma94f16a92020-06-26 04:17:55 +0000735func (PONRMgr *PONResourceManager) GetPath(ctx context.Context, IntfID uint32, ResourceType string) string {
Scott Baker2c1c4822019-10-16 11:02:41 -0700736 /*
737 Get path for given resource type.
738 :param pon_intf_id: OLT PON interface id
739 :param resource_type: String to identify type of resource
740 :return: path for given resource type
741 */
742
743 /*
744 Get the shared pool for the given resource type.
745 all the resource ranges and the shared resource maps are initialized during the init.
746 */
747 SharedPoolID := PONRMgr.PonResourceRanges[PONRMgr.SharedIdxByType[ResourceType]].(uint32)
748 if SharedPoolID != 0 {
749 IntfID = SharedPoolID
750 }
751 var Path string
Abhay Kumar40252eb2025-10-13 13:25:53 +0000752 switch ResourceType {
753 case ONU_ID:
Scott Baker2c1c4822019-10-16 11:02:41 -0700754 Path = fmt.Sprintf(ONU_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
Abhay Kumar40252eb2025-10-13 13:25:53 +0000755 case ALLOC_ID:
Scott Baker2c1c4822019-10-16 11:02:41 -0700756 Path = fmt.Sprintf(ALLOC_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
Abhay Kumar40252eb2025-10-13 13:25:53 +0000757 case GEMPORT_ID:
Scott Baker2c1c4822019-10-16 11:02:41 -0700758 Path = fmt.Sprintf(GEMPORT_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
Abhay Kumar40252eb2025-10-13 13:25:53 +0000759 case FLOW_ID:
Scott Baker2c1c4822019-10-16 11:02:41 -0700760 Path = fmt.Sprintf(FLOW_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
Abhay Kumar40252eb2025-10-13 13:25:53 +0000761 default:
Neha Sharma94f16a92020-06-26 04:17:55 +0000762 logger.Error(ctx, "Invalid resource pool identifier")
Scott Baker2c1c4822019-10-16 11:02:41 -0700763 }
764 return Path
765}
766
npujar5bf737f2020-01-16 19:35:25 +0530767func (PONRMgr *PONResourceManager) GetResourceID(ctx context.Context, IntfID uint32, ResourceType string, NumIDs uint32) ([]uint32, error) {
Scott Baker2c1c4822019-10-16 11:02:41 -0700768 /*
769 Create alloc/gemport/onu/flow id for given OLT PON interface.
770 :param pon_intf_id: OLT PON interface id
771 :param resource_type: String to identify type of resource
772 :param num_of_id: required number of ids
773 :return list/uint32/None: list, uint32 or None if resource type is
774 alloc_id/gemport_id, onu_id or invalid type respectively
775 */
Matteo Scandolob85b2f02021-03-18 14:44:41 -0700776
777 logger.Debugw(ctx, "getting-resource-id", log.Fields{
778 "intf-id": IntfID,
779 "resource-type": ResourceType,
780 "num": NumIDs,
781 })
782
Scott Baker2c1c4822019-10-16 11:02:41 -0700783 if NumIDs < 1 {
Neha Sharma94f16a92020-06-26 04:17:55 +0000784 logger.Error(ctx, "Invalid number of resources requested")
pnalmas37560752025-01-11 22:05:35 +0530785 return nil, fmt.Errorf("invalid number of resources requested %d", NumIDs)
Scott Baker2c1c4822019-10-16 11:02:41 -0700786 }
787 // delegate to the master instance if sharing enabled across instances
788
789 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
790 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
npujar5bf737f2020-01-16 19:35:25 +0530791 return SharedResourceMgr.GetResourceID(ctx, IntfID, ResourceType, NumIDs)
Scott Baker2c1c4822019-10-16 11:02:41 -0700792 }
Neha Sharma94f16a92020-06-26 04:17:55 +0000793 logger.Debugf(ctx, "Fetching resource from %s rsrc mgr for resource %s", PONRMgr.Globalorlocal, ResourceType)
Scott Baker2c1c4822019-10-16 11:02:41 -0700794
Neha Sharma94f16a92020-06-26 04:17:55 +0000795 Path := PONRMgr.GetPath(ctx, IntfID, ResourceType)
Scott Baker2c1c4822019-10-16 11:02:41 -0700796 if Path == "" {
Neha Sharma94f16a92020-06-26 04:17:55 +0000797 logger.Errorf(ctx, "Failed to get path for resource type %s", ResourceType)
pnalmas37560752025-01-11 22:05:35 +0530798 return nil, fmt.Errorf("failed to get path for resource type %s", ResourceType)
Scott Baker2c1c4822019-10-16 11:02:41 -0700799 }
Neha Sharma94f16a92020-06-26 04:17:55 +0000800 logger.Debugf(ctx, "Get resource for type %s on path %s", ResourceType, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700801 var Result []uint32
802 var NextID uint32
npujar5bf737f2020-01-16 19:35:25 +0530803 Resource, err := PONRMgr.GetResource(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700804 if (err == nil) && (ResourceType == ONU_ID) || (ResourceType == FLOW_ID) {
Neha Sharma94f16a92020-06-26 04:17:55 +0000805 if NextID, err = PONRMgr.GenerateNextID(ctx, Resource); err != nil {
806 logger.Error(ctx, "Failed to Generate ID")
Scott Baker2c1c4822019-10-16 11:02:41 -0700807 return Result, err
808 }
809 Result = append(Result, NextID)
810 } else if (err == nil) && ((ResourceType == GEMPORT_ID) || (ResourceType == ALLOC_ID)) {
811 if NumIDs == 1 {
Neha Sharma94f16a92020-06-26 04:17:55 +0000812 if NextID, err = PONRMgr.GenerateNextID(ctx, Resource); err != nil {
813 logger.Error(ctx, "Failed to Generate ID")
Scott Baker2c1c4822019-10-16 11:02:41 -0700814 return Result, err
815 }
816 Result = append(Result, NextID)
817 } else {
818 for NumIDs > 0 {
Neha Sharma94f16a92020-06-26 04:17:55 +0000819 if NextID, err = PONRMgr.GenerateNextID(ctx, Resource); err != nil {
820 logger.Error(ctx, "Failed to Generate ID")
Scott Baker2c1c4822019-10-16 11:02:41 -0700821 return Result, err
822 }
823 Result = append(Result, NextID)
824 NumIDs--
825 }
826 }
827 } else {
Neha Sharma94f16a92020-06-26 04:17:55 +0000828 logger.Error(ctx, "get resource failed")
Scott Baker2c1c4822019-10-16 11:02:41 -0700829 return Result, err
830 }
831
832 //Update resource in kv store
npujar5bf737f2020-01-16 19:35:25 +0530833 if PONRMgr.UpdateResource(ctx, Path, Resource) != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000834 logger.Errorf(ctx, "Failed to update resource %s", Path)
pnalmas37560752025-01-11 22:05:35 +0530835 return nil, fmt.Errorf("failed to update resource %s", Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700836 }
837 return Result, nil
838}
839
840func checkValidResourceType(ResourceType string) bool {
841 KnownResourceTypes := []string{ONU_ID, ALLOC_ID, GEMPORT_ID, FLOW_ID}
842
843 for _, v := range KnownResourceTypes {
844 if v == ResourceType {
845 return true
846 }
847 }
848 return false
849}
850
Matteo Scandolob85b2f02021-03-18 14:44:41 -0700851func (PONRMgr *PONResourceManager) FreeResourceID(ctx context.Context, IntfID uint32, ResourceType string, ReleaseContent []uint32) error {
Scott Baker2c1c4822019-10-16 11:02:41 -0700852 /*
Matteo Scandolob85b2f02021-03-18 14:44:41 -0700853 Release alloc/gemport/onu/flow id for given OLT PON interface.
854 :param pon_intf_id: OLT PON interface id
855 :param resource_type: String to identify type of resource
856 :param release_content: required number of ids
857 :return boolean: True if all IDs in given release_content release else False
Scott Baker2c1c4822019-10-16 11:02:41 -0700858 */
Matteo Scandolob85b2f02021-03-18 14:44:41 -0700859
860 logger.Debugw(ctx, "freeing-resource-id", log.Fields{
861 "intf-id": IntfID,
862 "resource-type": ResourceType,
863 "release-content": ReleaseContent,
864 })
865
David K. Bainbridge7c75cac2020-02-19 08:53:46 -0800866 if !checkValidResourceType(ResourceType) {
pnalmas37560752025-01-11 22:05:35 +0530867 err := fmt.Errorf("invalid resource type: %s", ResourceType)
Matteo Scandolob85b2f02021-03-18 14:44:41 -0700868 logger.Error(ctx, err.Error())
869 return err
Scott Baker2c1c4822019-10-16 11:02:41 -0700870 }
871 if ReleaseContent == nil {
pnalmas37560752025-01-11 22:05:35 +0530872 err := fmt.Errorf("nothing to release")
Matteo Scandolob85b2f02021-03-18 14:44:41 -0700873 logger.Debug(ctx, err.Error())
874 return err
Scott Baker2c1c4822019-10-16 11:02:41 -0700875 }
876 // delegate to the master instance if sharing enabled across instances
877 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
878 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
npujar5bf737f2020-01-16 19:35:25 +0530879 return SharedResourceMgr.FreeResourceID(ctx, IntfID, ResourceType, ReleaseContent)
Scott Baker2c1c4822019-10-16 11:02:41 -0700880 }
Neha Sharma94f16a92020-06-26 04:17:55 +0000881 Path := PONRMgr.GetPath(ctx, IntfID, ResourceType)
Scott Baker2c1c4822019-10-16 11:02:41 -0700882 if Path == "" {
pnalmas37560752025-01-11 22:05:35 +0530883 err := fmt.Errorf("failed to get path for IntfId %d and ResourceType %s", IntfID, ResourceType)
Matteo Scandolob85b2f02021-03-18 14:44:41 -0700884 logger.Error(ctx, err.Error())
885 return err
Scott Baker2c1c4822019-10-16 11:02:41 -0700886 }
npujar5bf737f2020-01-16 19:35:25 +0530887 Resource, err := PONRMgr.GetResource(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700888 if err != nil {
Matteo Scandolob85b2f02021-03-18 14:44:41 -0700889 logger.Error(ctx, err.Error())
890 return err
Scott Baker2c1c4822019-10-16 11:02:41 -0700891 }
892 for _, Val := range ReleaseContent {
Neha Sharma94f16a92020-06-26 04:17:55 +0000893 PONRMgr.ReleaseID(ctx, Resource, Val)
Scott Baker2c1c4822019-10-16 11:02:41 -0700894 }
npujar5bf737f2020-01-16 19:35:25 +0530895 if PONRMgr.UpdateResource(ctx, Path, Resource) != nil {
pnalmas37560752025-01-11 22:05:35 +0530896 err := fmt.Errorf("free resource for %s failed", Path)
Matteo Scandolob85b2f02021-03-18 14:44:41 -0700897 logger.Errorf(ctx, err.Error())
898 return err
Scott Baker2c1c4822019-10-16 11:02:41 -0700899 }
Matteo Scandolob85b2f02021-03-18 14:44:41 -0700900 return nil
Scott Baker2c1c4822019-10-16 11:02:41 -0700901}
902
npujar5bf737f2020-01-16 19:35:25 +0530903func (PONRMgr *PONResourceManager) UpdateResource(ctx context.Context, Path string, Resource map[string]interface{}) error {
Scott Baker2c1c4822019-10-16 11:02:41 -0700904 /*
905 Update resource in resource kv store.
906 :param path: path to update resource
907 :param resource: resource need to be updated
908 :return boolean: True if resource updated in kv store else False
909 */
910 // TODO resource[POOL] = resource[POOL].bin
911 Value, err := json.Marshal(Resource)
912 if err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000913 logger.Error(ctx, "failed to Marshal")
Scott Baker2c1c4822019-10-16 11:02:41 -0700914 return err
915 }
npujar5bf737f2020-01-16 19:35:25 +0530916 err = PONRMgr.KVStore.Put(ctx, Path, Value)
Scott Baker2c1c4822019-10-16 11:02:41 -0700917 if err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000918 logger.Error(ctx, "failed to put data to kv store %s", Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700919 return err
920 }
921 return nil
922}
923
npujar5bf737f2020-01-16 19:35:25 +0530924func (PONRMgr *PONResourceManager) ClearResourceIDPool(ctx context.Context, contIntfID uint32, ResourceType string) bool {
Scott Baker2c1c4822019-10-16 11:02:41 -0700925 /*
926 Clear Resource Pool for a given Resource Type on a given PON Port.
927 :return boolean: True if removed else False
928 */
929
930 // delegate to the master instance if sharing enabled across instances
931 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
932 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
npujar5bf737f2020-01-16 19:35:25 +0530933 return SharedResourceMgr.ClearResourceIDPool(ctx, contIntfID, ResourceType)
Scott Baker2c1c4822019-10-16 11:02:41 -0700934 }
Neha Sharma94f16a92020-06-26 04:17:55 +0000935 Path := PONRMgr.GetPath(ctx, contIntfID, ResourceType)
Scott Baker2c1c4822019-10-16 11:02:41 -0700936 if Path == "" {
Neha Sharma94f16a92020-06-26 04:17:55 +0000937 logger.Error(ctx, "Failed to get path")
Scott Baker2c1c4822019-10-16 11:02:41 -0700938 return false
939 }
940
npujar5bf737f2020-01-16 19:35:25 +0530941 if err := PONRMgr.KVStore.Delete(ctx, Path); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000942 logger.Errorf(ctx, "Failed to delete resource %s", Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700943 return false
944 }
Neha Sharma94f16a92020-06-26 04:17:55 +0000945 logger.Debugf(ctx, "Cleared resource %s", Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700946 return true
947}
948
npujar5bf737f2020-01-16 19:35:25 +0530949func (PONRMgr PONResourceManager) InitResourceMap(ctx context.Context, PONIntfONUID string) {
Scott Baker2c1c4822019-10-16 11:02:41 -0700950 /*
951 Initialize resource map
952 :param pon_intf_onu_id: reference of PON interface id and onu id
953 */
954 // initialize pon_intf_onu_id tuple to alloc_ids map
955 AllocIDPath := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
956 var AllocIDs []byte
npujar5bf737f2020-01-16 19:35:25 +0530957 Result := PONRMgr.KVStore.Put(ctx, AllocIDPath, AllocIDs)
Scott Baker2c1c4822019-10-16 11:02:41 -0700958 if Result != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000959 logger.Error(ctx, "Failed to update the KV store")
Scott Baker2c1c4822019-10-16 11:02:41 -0700960 return
961 }
962 // initialize pon_intf_onu_id tuple to gemport_ids map
963 GEMPortIDPath := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
964 var GEMPortIDs []byte
npujar5bf737f2020-01-16 19:35:25 +0530965 Result = PONRMgr.KVStore.Put(ctx, GEMPortIDPath, GEMPortIDs)
Scott Baker2c1c4822019-10-16 11:02:41 -0700966 if Result != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000967 logger.Error(ctx, "Failed to update the KV store")
Scott Baker2c1c4822019-10-16 11:02:41 -0700968 return
969 }
970}
971
npujar5bf737f2020-01-16 19:35:25 +0530972func (PONRMgr PONResourceManager) RemoveResourceMap(ctx context.Context, PONIntfONUID string) bool {
Scott Baker2c1c4822019-10-16 11:02:41 -0700973 /*
974 Remove resource map
975 :param pon_intf_onu_id: reference of PON interface id and onu id
976 */
977 // remove pon_intf_onu_id tuple to alloc_ids map
978 var err error
979 AllocIDPath := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
npujar5bf737f2020-01-16 19:35:25 +0530980 if err = PONRMgr.KVStore.Delete(ctx, AllocIDPath); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000981 logger.Errorf(ctx, "Failed to remove resource %s", AllocIDPath)
Scott Baker2c1c4822019-10-16 11:02:41 -0700982 return false
983 }
984 // remove pon_intf_onu_id tuple to gemport_ids map
985 GEMPortIDPath := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
npujar5bf737f2020-01-16 19:35:25 +0530986 err = PONRMgr.KVStore.Delete(ctx, GEMPortIDPath)
Scott Baker2c1c4822019-10-16 11:02:41 -0700987 if err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000988 logger.Errorf(ctx, "Failed to remove resource %s", GEMPortIDPath)
Scott Baker2c1c4822019-10-16 11:02:41 -0700989 return false
990 }
991
992 FlowIDPath := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
npujar5bf737f2020-01-16 19:35:25 +0530993 if FlowIDs, err := PONRMgr.KVStore.List(ctx, FlowIDPath); err != nil {
Scott Baker2c1c4822019-10-16 11:02:41 -0700994 for _, Flow := range FlowIDs {
995 FlowIDInfoPath := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, PONIntfONUID, Flow.Value)
npujar5bf737f2020-01-16 19:35:25 +0530996 if err = PONRMgr.KVStore.Delete(ctx, FlowIDInfoPath); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000997 logger.Errorf(ctx, "Failed to remove resource %s", FlowIDInfoPath)
Scott Baker2c1c4822019-10-16 11:02:41 -0700998 return false
999 }
1000 }
1001 }
1002
npujar5bf737f2020-01-16 19:35:25 +05301003 if err = PONRMgr.KVStore.Delete(ctx, FlowIDPath); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001004 logger.Errorf(ctx, "Failed to remove resource %s", FlowIDPath)
Scott Baker2c1c4822019-10-16 11:02:41 -07001005 return false
1006 }
1007
1008 return true
1009}
1010
npujar5bf737f2020-01-16 19:35:25 +05301011func (PONRMgr *PONResourceManager) GetCurrentAllocIDForOnu(ctx context.Context, IntfONUID string) []uint32 {
Scott Baker2c1c4822019-10-16 11:02:41 -07001012 /*
1013 Get currently configured alloc ids for given pon_intf_onu_id
1014 :param pon_intf_onu_id: reference of PON interface id and onu id
1015 :return list: List of alloc_ids if available, else None
1016 */
1017 Path := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
1018
1019 var Data []uint32
npujar5bf737f2020-01-16 19:35:25 +05301020 Value, err := PONRMgr.KVStore.Get(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -07001021 if err == nil {
1022 if Value != nil {
1023 Val, err := ToByte(Value.Value)
1024 if err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001025 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"error": err})
Scott Baker2c1c4822019-10-16 11:02:41 -07001026 return Data
1027 }
1028 if err = json.Unmarshal(Val, &Data); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001029 logger.Error(ctx, "Failed to unmarshal", log.Fields{"error": err})
Scott Baker2c1c4822019-10-16 11:02:41 -07001030 return Data
1031 }
1032 }
1033 }
1034 return Data
1035}
1036
npujar5bf737f2020-01-16 19:35:25 +05301037func (PONRMgr *PONResourceManager) GetCurrentGEMPortIDsForOnu(ctx context.Context, IntfONUID string) []uint32 {
Scott Baker2c1c4822019-10-16 11:02:41 -07001038 /*
1039 Get currently configured gemport ids for given pon_intf_onu_id
1040 :param pon_intf_onu_id: reference of PON interface id and onu id
1041 :return list: List of gemport IDs if available, else None
1042 */
1043
1044 Path := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
Neha Sharma94f16a92020-06-26 04:17:55 +00001045 logger.Debugf(ctx, "Getting current gemports for %s", Path)
Scott Baker2c1c4822019-10-16 11:02:41 -07001046 var Data []uint32
npujar5bf737f2020-01-16 19:35:25 +05301047 Value, err := PONRMgr.KVStore.Get(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -07001048 if err == nil {
1049 if Value != nil {
1050 Val, _ := ToByte(Value.Value)
1051 if err = json.Unmarshal(Val, &Data); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001052 logger.Errorw(ctx, "Failed to unmarshal", log.Fields{"error": err})
Scott Baker2c1c4822019-10-16 11:02:41 -07001053 return Data
1054 }
1055 }
1056 } else {
Neha Sharma94f16a92020-06-26 04:17:55 +00001057 logger.Errorf(ctx, "Failed to get data from kvstore for %s", Path)
Scott Baker2c1c4822019-10-16 11:02:41 -07001058 }
1059 return Data
1060}
1061
npujar5bf737f2020-01-16 19:35:25 +05301062func (PONRMgr *PONResourceManager) GetCurrentFlowIDsForOnu(ctx context.Context, IntfONUID string) []uint32 {
Scott Baker2c1c4822019-10-16 11:02:41 -07001063 /*
1064 Get currently configured flow ids for given pon_intf_onu_id
1065 :param pon_intf_onu_id: reference of PON interface id and onu id
1066 :return list: List of Flow IDs if available, else None
1067 */
1068
1069 Path := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
1070
1071 var Data []uint32
npujar5bf737f2020-01-16 19:35:25 +05301072 Value, err := PONRMgr.KVStore.Get(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -07001073 if err == nil {
1074 if Value != nil {
1075 Val, _ := ToByte(Value.Value)
1076 if err = json.Unmarshal(Val, &Data); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001077 logger.Error(ctx, "Failed to unmarshal")
Scott Baker2c1c4822019-10-16 11:02:41 -07001078 return Data
1079 }
1080 }
1081 }
1082 return Data
1083}
1084
npujar5bf737f2020-01-16 19:35:25 +05301085func (PONRMgr *PONResourceManager) GetFlowIDInfo(ctx context.Context, IntfONUID string, FlowID uint32, Data interface{}) error {
Scott Baker2c1c4822019-10-16 11:02:41 -07001086 /*
1087 Get flow details configured for the ONU.
1088 :param pon_intf_onu_id: reference of PON interface id and onu id
1089 :param flow_id: Flow Id reference
1090 :param Data: Result
1091 :return error: nil if no error in getting from KV store
1092 */
1093
1094 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
1095
npujar5bf737f2020-01-16 19:35:25 +05301096 Value, err := PONRMgr.KVStore.Get(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -07001097 if err == nil {
1098 if Value != nil {
1099 Val, err := ToByte(Value.Value)
1100 if err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001101 logger.Errorw(ctx, "Failed to convert flowinfo into byte array", log.Fields{"error": err})
Scott Baker2c1c4822019-10-16 11:02:41 -07001102 return err
1103 }
1104 if err = json.Unmarshal(Val, Data); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001105 logger.Errorw(ctx, "Failed to unmarshal", log.Fields{"error": err})
Scott Baker2c1c4822019-10-16 11:02:41 -07001106 return err
1107 }
1108 }
1109 }
1110 return err
1111}
1112
npujar5bf737f2020-01-16 19:35:25 +05301113func (PONRMgr *PONResourceManager) RemoveFlowIDInfo(ctx context.Context, IntfONUID string, FlowID uint32) bool {
Scott Baker2c1c4822019-10-16 11:02:41 -07001114 /*
1115 Get flow_id details configured for the ONU.
1116 :param pon_intf_onu_id: reference of PON interface id and onu id
1117 :param flow_id: Flow Id reference
1118 */
1119 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
1120
npujar5bf737f2020-01-16 19:35:25 +05301121 if err := PONRMgr.KVStore.Delete(ctx, Path); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001122 logger.Errorf(ctx, "Falied to remove resource %s", Path)
Scott Baker2c1c4822019-10-16 11:02:41 -07001123 return false
1124 }
1125 return true
1126}
1127
Serkant Uluderya198de902020-11-16 20:29:17 +03001128func (PONRMgr *PONResourceManager) RemoveAllFlowIDInfo(ctx context.Context, IntfONUID string) bool {
1129 /*
1130 Remove flow_id_info details configured for the ONU.
1131 :param pon_intf_onu_id: reference of PON interface id and onu id
1132 */
1133 Path := fmt.Sprintf(FLOW_ID_INFO_PATH_INTF_ONU_PREFIX, PONRMgr.DeviceID, IntfONUID)
1134
1135 if err := PONRMgr.KVStore.DeleteWithPrefix(ctx, Path); err != nil {
1136 logger.Errorf(ctx, "Falied to remove resource %s", Path)
1137 return false
1138 }
1139 return true
1140}
1141
npujar5bf737f2020-01-16 19:35:25 +05301142func (PONRMgr *PONResourceManager) UpdateAllocIdsForOnu(ctx context.Context, IntfONUID string, AllocIDs []uint32) error {
Scott Baker2c1c4822019-10-16 11:02:41 -07001143 /*
1144 Update currently configured alloc ids for given pon_intf_onu_id
1145 :param pon_intf_onu_id: reference of PON interface id and onu id
1146 :param alloc_ids: list of alloc ids
1147 */
1148 var Value []byte
1149 var err error
1150 Path := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
Girish Gowdra823da1d2021-10-28 11:47:53 -07001151 if AllocIDs == nil {
1152 // No more alloc ids associated with the key. Delete the key entirely
1153 if err = PONRMgr.KVStore.Delete(ctx, Path); err != nil {
1154 logger.Errorf(ctx, "Failed to delete key %s", Path)
1155 return err
1156 }
1157 } else {
1158 Value, err = json.Marshal(AllocIDs)
1159 if err != nil {
1160 logger.Error(ctx, "failed to Marshal")
1161 return err
1162 }
Scott Baker2c1c4822019-10-16 11:02:41 -07001163
Girish Gowdra823da1d2021-10-28 11:47:53 -07001164 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
1165 logger.Errorf(ctx, "Failed to update resource %s", Path)
1166 return err
1167 }
Scott Baker2c1c4822019-10-16 11:02:41 -07001168 }
1169 return err
1170}
1171
npujar5bf737f2020-01-16 19:35:25 +05301172func (PONRMgr *PONResourceManager) UpdateGEMPortIDsForOnu(ctx context.Context, IntfONUID string, GEMPortIDs []uint32) error {
Scott Baker2c1c4822019-10-16 11:02:41 -07001173 /*
1174 Update currently configured gemport ids for given pon_intf_onu_id
1175 :param pon_intf_onu_id: reference of PON interface id and onu id
1176 :param gemport_ids: list of gem port ids
1177 */
1178
1179 var Value []byte
1180 var err error
1181 Path := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
Neha Sharma94f16a92020-06-26 04:17:55 +00001182 logger.Debugf(ctx, "Updating gemport ids for %s", Path)
Girish Gowdra823da1d2021-10-28 11:47:53 -07001183 if GEMPortIDs == nil {
1184 // No more gemport ids associated with the key. Delete the key entirely
1185 if err = PONRMgr.KVStore.Delete(ctx, Path); err != nil {
1186 logger.Errorf(ctx, "Failed to delete key %s", Path)
1187 return err
1188 }
1189 } else {
1190 Value, err = json.Marshal(GEMPortIDs)
1191 if err != nil {
1192 logger.Error(ctx, "failed to Marshal")
1193 return err
1194 }
Scott Baker2c1c4822019-10-16 11:02:41 -07001195
Girish Gowdra823da1d2021-10-28 11:47:53 -07001196 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
1197 logger.Errorf(ctx, "Failed to update resource %s", Path)
1198 return err
1199 }
Scott Baker2c1c4822019-10-16 11:02:41 -07001200 }
1201 return err
1202}
1203
1204func checkForFlowIDInList(FlowIDList []uint32, FlowID uint32) (bool, uint32) {
1205 /*
1206 Check for a flow id in a given list of flow IDs.
1207 :param FLowIDList: List of Flow IDs
1208 :param FlowID: Flowd to check in the list
1209 : return true and the index if present false otherwise.
1210 */
1211
David K. Bainbridge7c75cac2020-02-19 08:53:46 -08001212 for idx := range FlowIDList {
Scott Baker2c1c4822019-10-16 11:02:41 -07001213 if FlowID == FlowIDList[idx] {
1214 return true, uint32(idx)
1215 }
1216 }
1217 return false, 0
1218}
1219
npujar5bf737f2020-01-16 19:35:25 +05301220func (PONRMgr *PONResourceManager) UpdateFlowIDForOnu(ctx context.Context, IntfONUID string, FlowID uint32, Add bool) error {
Scott Baker2c1c4822019-10-16 11:02:41 -07001221 /*
1222 Update the flow_id list of the ONU (add or remove flow_id from the list)
1223 :param pon_intf_onu_id: reference of PON interface id and onu id
1224 :param flow_id: flow ID
1225 :param add: Boolean flag to indicate whether the flow_id should be
1226 added or removed from the list. Defaults to adding the flow.
1227 */
1228 var Value []byte
1229 var err error
1230 var RetVal bool
1231 var IDx uint32
1232 Path := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
npujar5bf737f2020-01-16 19:35:25 +05301233 FlowIDs := PONRMgr.GetCurrentFlowIDsForOnu(ctx, IntfONUID)
Scott Baker2c1c4822019-10-16 11:02:41 -07001234
1235 if Add {
David K. Bainbridge7c75cac2020-02-19 08:53:46 -08001236 if RetVal, _ = checkForFlowIDInList(FlowIDs, FlowID); RetVal {
1237 return nil
Scott Baker2c1c4822019-10-16 11:02:41 -07001238 }
1239 FlowIDs = append(FlowIDs, FlowID)
1240 } else {
David K. Bainbridge7c75cac2020-02-19 08:53:46 -08001241 if RetVal, IDx = checkForFlowIDInList(FlowIDs, FlowID); !RetVal {
1242 return nil
Scott Baker2c1c4822019-10-16 11:02:41 -07001243 }
1244 // delete the index and shift
1245 FlowIDs = append(FlowIDs[:IDx], FlowIDs[IDx+1:]...)
1246 }
1247 Value, err = json.Marshal(FlowIDs)
1248 if err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001249 logger.Error(ctx, "Failed to Marshal")
Scott Baker2c1c4822019-10-16 11:02:41 -07001250 return err
1251 }
1252
npujar5bf737f2020-01-16 19:35:25 +05301253 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001254 logger.Errorf(ctx, "Failed to update resource %s", Path)
Scott Baker2c1c4822019-10-16 11:02:41 -07001255 return err
1256 }
1257 return err
1258}
1259
npujar5bf737f2020-01-16 19:35:25 +05301260func (PONRMgr *PONResourceManager) UpdateFlowIDInfoForOnu(ctx context.Context, IntfONUID string, FlowID uint32, FlowData interface{}) error {
Scott Baker2c1c4822019-10-16 11:02:41 -07001261 /*
1262 Update any metadata associated with the flow_id. The flow_data could be json
1263 or any of other data structure. The resource manager doesnt care
1264 :param pon_intf_onu_id: reference of PON interface id and onu id
1265 :param flow_id: Flow ID
1266 :param flow_data: Flow data blob
1267 */
1268 var Value []byte
1269 var err error
1270 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
1271 Value, err = json.Marshal(FlowData)
1272 if err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001273 logger.Error(ctx, "failed to Marshal")
Scott Baker2c1c4822019-10-16 11:02:41 -07001274 return err
1275 }
1276
npujar5bf737f2020-01-16 19:35:25 +05301277 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001278 logger.Errorf(ctx, "Failed to update resource %s", Path)
Scott Baker2c1c4822019-10-16 11:02:41 -07001279 return err
1280 }
1281 return err
1282}
1283
Neha Sharma94f16a92020-06-26 04:17:55 +00001284func (PONRMgr *PONResourceManager) GenerateNextID(ctx context.Context, Resource map[string]interface{}) (uint32, error) {
Scott Baker2c1c4822019-10-16 11:02:41 -07001285 /*
1286 Generate unique id having OFFSET as start
1287 :param resource: resource used to generate ID
1288 :return uint32: generated id
1289 */
1290 ByteArray, err := ToByte(Resource[POOL])
1291 if err != nil {
Scott Baker2c1c4822019-10-16 11:02:41 -07001292 return 0, err
1293 }
1294 Data := bitmap.TSFromData(ByteArray, false)
1295 if Data == nil {
pnalmas37560752025-01-11 22:05:35 +05301296 return 0, errors.New("failed to get data from byte array")
Scott Baker2c1c4822019-10-16 11:02:41 -07001297 }
1298
1299 Len := Data.Len()
1300 var Idx int
1301 for Idx = 0; Idx < Len; Idx++ {
David K. Bainbridge7c75cac2020-02-19 08:53:46 -08001302 if !Data.Get(Idx) {
Scott Baker2c1c4822019-10-16 11:02:41 -07001303 break
1304 }
1305 }
Esin Karamanefab54e2021-10-13 11:11:43 +00001306 if Idx == Len {
1307 return 0, errors.New("resource-exhausted--no-free-id-in-the-pool")
1308 }
Scott Baker2c1c4822019-10-16 11:02:41 -07001309 Data.Set(Idx, true)
1310 res := uint32(Resource[START_IDX].(float64))
1311 Resource[POOL] = Data.Data(false)
Neha Sharma94f16a92020-06-26 04:17:55 +00001312 logger.Debugf(ctx, "Generated ID for %d", (uint32(Idx) + res))
Scott Baker2c1c4822019-10-16 11:02:41 -07001313 return (uint32(Idx) + res), err
1314}
1315
Neha Sharma94f16a92020-06-26 04:17:55 +00001316func (PONRMgr *PONResourceManager) ReleaseID(ctx context.Context, Resource map[string]interface{}, Id uint32) bool {
Scott Baker2c1c4822019-10-16 11:02:41 -07001317 /*
1318 Release unique id having OFFSET as start index.
1319 :param resource: resource used to release ID
1320 :param unique_id: id need to be released
1321 */
1322 ByteArray, err := ToByte(Resource[POOL])
1323 if err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001324 logger.Error(ctx, "Failed to convert resource to byte array")
Scott Baker2c1c4822019-10-16 11:02:41 -07001325 return false
1326 }
1327 Data := bitmap.TSFromData(ByteArray, false)
1328 if Data == nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001329 logger.Error(ctx, "Failed to get resource pool")
Scott Baker2c1c4822019-10-16 11:02:41 -07001330 return false
1331 }
David K. Bainbridge7c75cac2020-02-19 08:53:46 -08001332 Idx := Id - uint32(Resource[START_IDX].(float64))
Esin Karamanefab54e2021-10-13 11:11:43 +00001333 if Idx >= uint32(Data.Len()) {
1334 logger.Errorf(ctx, "ID %d is out of the boundaries of the pool", Id)
1335 return false
1336 }
Scott Baker2c1c4822019-10-16 11:02:41 -07001337 Data.Set(int(Idx), false)
1338 Resource[POOL] = Data.Data(false)
1339
1340 return true
1341}
1342
Joey Armstrong7f8436c2023-07-09 20:23:27 -04001343/*
1344 Reserves a unique id in the specified resource pool.
1345
Esin Karaman5351fc52020-02-14 07:45:49 +00001346:param Resource: resource used to reserve ID
1347:param Id: ID to be reserved
1348*/
Neha Sharma94f16a92020-06-26 04:17:55 +00001349func (PONRMgr *PONResourceManager) reserveID(ctx context.Context, TSData *bitmap.Threadsafe, StartIndex uint32, Id uint32) bool {
Esin Karaman5351fc52020-02-14 07:45:49 +00001350 Data := bitmap.TSFromData(TSData.Data(false), false)
1351 if Data == nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001352 logger.Error(ctx, "Failed to get resource pool")
Esin Karaman5351fc52020-02-14 07:45:49 +00001353 return false
1354 }
1355 Idx := Id - StartIndex
Esin Karamanefab54e2021-10-13 11:11:43 +00001356 if Idx >= uint32(Data.Len()) {
1357 logger.Errorf(ctx, "Reservation failed. ID %d is out of the boundaries of the pool", Id)
1358 return false
1359 }
Esin Karaman5351fc52020-02-14 07:45:49 +00001360 Data.Set(int(Idx), true)
1361 return true
1362}
1363
Scott Baker2c1c4822019-10-16 11:02:41 -07001364func (PONRMgr *PONResourceManager) GetTechnology() string {
1365 return PONRMgr.Technology
1366}
1367
1368func (PONRMgr *PONResourceManager) GetResourceTypeAllocID() string {
1369 return ALLOC_ID
1370}
1371
1372func (PONRMgr *PONResourceManager) GetResourceTypeGemPortID() string {
1373 return GEMPORT_ID
1374}
1375
Matteo Scandolob85b2f02021-03-18 14:44:41 -07001376func (PONRMgr *PONResourceManager) GetResourceTypeOnuID() string {
1377 return ONU_ID
1378}
1379
Scott Baker2c1c4822019-10-16 11:02:41 -07001380// ToByte converts an interface value to a []byte. The interface should either be of
1381// a string type or []byte. Otherwise, an error is returned.
1382func ToByte(value interface{}) ([]byte, error) {
1383 switch t := value.(type) {
1384 case []byte:
1385 return value.([]byte), nil
1386 case string:
1387 return []byte(value.(string)), nil
1388 default:
1389 return nil, fmt.Errorf("unexpected-type-%T", t)
1390 }
1391}
1392
1393// ToString converts an interface value to a string. The interface should either be of
1394// a string type or []byte. Otherwise, an error is returned.
1395func ToString(value interface{}) (string, error) {
1396 switch t := value.(type) {
1397 case []byte:
1398 return string(value.([]byte)), nil
1399 case string:
1400 return value.(string), nil
1401 default:
1402 return "", fmt.Errorf("unexpected-type-%T", t)
1403 }
1404}