blob: 807d4c81d97f99b945b13b4ec97826ad54e43a72 [file] [log] [blame]
Scott Baker2c1c4822019-10-16 11:02:41 -07001/*
2 * Copyright 2019-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
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")
Scott Baker2c1c4822019-10-16 11:02:41 -0700217 return nil, errors.New("Failed to init KV client")
218 }
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")
Esin Karaman5351fc52020-02-14 07:45:49 +0000223 return nil, errors.New("Failed to init KV Config client")
224 }
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")
Scott Baker2c1c4822019-10-16 11:02:41 -0700486 return errors.New("Failed to clear ONU ID resource pool")
487 }
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 ")
Scott Baker2c1c4822019-10-16 11:02:41 -0700500 return errors.New("Failed to clear ALLOC ID resource pool")
501 }
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")
Scott Baker2c1c4822019-10-16 11:02:41 -0700513 return errors.New("Failed to clear GEMPORT ID resource pool")
514 }
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")
Scott Baker2c1c4822019-10-16 11:02:41 -0700527 return errors.New("Failed to clear FLOW ID resource pool")
528 }
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")
542 return errors.New("Failed to clear ONU ID resource pool")
543 }
544
545 if status := PONRMgr.ClearResourceIDPool(ctx, intfID, ALLOC_ID); !status {
546 logger.Error(ctx, "Failed to clear ALLOC ID resource pool ")
547 return errors.New("Failed to clear ALLOC ID resource pool")
548 }
549
550 if status := PONRMgr.ClearResourceIDPool(ctx, intfID, GEMPORT_ID); !status {
551 logger.Error(ctx, "Failed to clear GEMPORT ID resource pool")
552 return errors.New("Failed to clear GEMPORT ID resource pool")
553 }
554
555 if status := PONRMgr.ClearResourceIDPool(ctx, intfID, FLOW_ID); !status {
556 logger.Error(ctx, "Failed to clear FLOW ID resource pool")
557 return errors.New("Failed to clear FLOW ID resource pool")
558 }
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)
David K. Bainbridge7c75cac2020-02-19 08:53:46 -0800583 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")
Scott Baker2c1c4822019-10-16 11:02:41 -0700666 return nil, errors.New("Failed to create bitmap")
667 }
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
752 if ResourceType == ONU_ID {
753 Path = fmt.Sprintf(ONU_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
754 } else if ResourceType == ALLOC_ID {
755 Path = fmt.Sprintf(ALLOC_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
756 } else if ResourceType == GEMPORT_ID {
757 Path = fmt.Sprintf(GEMPORT_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
758 } else if ResourceType == FLOW_ID {
759 Path = fmt.Sprintf(FLOW_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
760 } else {
Neha Sharma94f16a92020-06-26 04:17:55 +0000761 logger.Error(ctx, "Invalid resource pool identifier")
Scott Baker2c1c4822019-10-16 11:02:41 -0700762 }
763 return Path
764}
765
npujar5bf737f2020-01-16 19:35:25 +0530766func (PONRMgr *PONResourceManager) GetResourceID(ctx context.Context, IntfID uint32, ResourceType string, NumIDs uint32) ([]uint32, error) {
Scott Baker2c1c4822019-10-16 11:02:41 -0700767 /*
768 Create alloc/gemport/onu/flow id for given OLT PON interface.
769 :param pon_intf_id: OLT PON interface id
770 :param resource_type: String to identify type of resource
771 :param num_of_id: required number of ids
772 :return list/uint32/None: list, uint32 or None if resource type is
773 alloc_id/gemport_id, onu_id or invalid type respectively
774 */
Matteo Scandolob85b2f02021-03-18 14:44:41 -0700775
776 logger.Debugw(ctx, "getting-resource-id", log.Fields{
777 "intf-id": IntfID,
778 "resource-type": ResourceType,
779 "num": NumIDs,
780 })
781
Scott Baker2c1c4822019-10-16 11:02:41 -0700782 if NumIDs < 1 {
Neha Sharma94f16a92020-06-26 04:17:55 +0000783 logger.Error(ctx, "Invalid number of resources requested")
David K. Bainbridge7c75cac2020-02-19 08:53:46 -0800784 return nil, fmt.Errorf("Invalid number of resources requested %d", NumIDs)
Scott Baker2c1c4822019-10-16 11:02:41 -0700785 }
786 // delegate to the master instance if sharing enabled across instances
787
788 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
789 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
npujar5bf737f2020-01-16 19:35:25 +0530790 return SharedResourceMgr.GetResourceID(ctx, IntfID, ResourceType, NumIDs)
Scott Baker2c1c4822019-10-16 11:02:41 -0700791 }
Neha Sharma94f16a92020-06-26 04:17:55 +0000792 logger.Debugf(ctx, "Fetching resource from %s rsrc mgr for resource %s", PONRMgr.Globalorlocal, ResourceType)
Scott Baker2c1c4822019-10-16 11:02:41 -0700793
Neha Sharma94f16a92020-06-26 04:17:55 +0000794 Path := PONRMgr.GetPath(ctx, IntfID, ResourceType)
Scott Baker2c1c4822019-10-16 11:02:41 -0700795 if Path == "" {
Neha Sharma94f16a92020-06-26 04:17:55 +0000796 logger.Errorf(ctx, "Failed to get path for resource type %s", ResourceType)
David K. Bainbridge7c75cac2020-02-19 08:53:46 -0800797 return nil, fmt.Errorf("Failed to get path for resource type %s", ResourceType)
Scott Baker2c1c4822019-10-16 11:02:41 -0700798 }
Neha Sharma94f16a92020-06-26 04:17:55 +0000799 logger.Debugf(ctx, "Get resource for type %s on path %s", ResourceType, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700800 var Result []uint32
801 var NextID uint32
npujar5bf737f2020-01-16 19:35:25 +0530802 Resource, err := PONRMgr.GetResource(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700803 if (err == nil) && (ResourceType == ONU_ID) || (ResourceType == FLOW_ID) {
Neha Sharma94f16a92020-06-26 04:17:55 +0000804 if NextID, err = PONRMgr.GenerateNextID(ctx, Resource); err != nil {
805 logger.Error(ctx, "Failed to Generate ID")
Scott Baker2c1c4822019-10-16 11:02:41 -0700806 return Result, err
807 }
808 Result = append(Result, NextID)
809 } else if (err == nil) && ((ResourceType == GEMPORT_ID) || (ResourceType == ALLOC_ID)) {
810 if NumIDs == 1 {
Neha Sharma94f16a92020-06-26 04:17:55 +0000811 if NextID, err = PONRMgr.GenerateNextID(ctx, Resource); err != nil {
812 logger.Error(ctx, "Failed to Generate ID")
Scott Baker2c1c4822019-10-16 11:02:41 -0700813 return Result, err
814 }
815 Result = append(Result, NextID)
816 } else {
817 for NumIDs > 0 {
Neha Sharma94f16a92020-06-26 04:17:55 +0000818 if NextID, err = PONRMgr.GenerateNextID(ctx, Resource); err != nil {
819 logger.Error(ctx, "Failed to Generate ID")
Scott Baker2c1c4822019-10-16 11:02:41 -0700820 return Result, err
821 }
822 Result = append(Result, NextID)
823 NumIDs--
824 }
825 }
826 } else {
Neha Sharma94f16a92020-06-26 04:17:55 +0000827 logger.Error(ctx, "get resource failed")
Scott Baker2c1c4822019-10-16 11:02:41 -0700828 return Result, err
829 }
830
831 //Update resource in kv store
npujar5bf737f2020-01-16 19:35:25 +0530832 if PONRMgr.UpdateResource(ctx, Path, Resource) != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000833 logger.Errorf(ctx, "Failed to update resource %s", Path)
David K. Bainbridge7c75cac2020-02-19 08:53:46 -0800834 return nil, fmt.Errorf("Failed to update resource %s", Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700835 }
836 return Result, nil
837}
838
839func checkValidResourceType(ResourceType string) bool {
840 KnownResourceTypes := []string{ONU_ID, ALLOC_ID, GEMPORT_ID, FLOW_ID}
841
842 for _, v := range KnownResourceTypes {
843 if v == ResourceType {
844 return true
845 }
846 }
847 return false
848}
849
Matteo Scandolob85b2f02021-03-18 14:44:41 -0700850func (PONRMgr *PONResourceManager) FreeResourceID(ctx context.Context, IntfID uint32, ResourceType string, ReleaseContent []uint32) error {
Scott Baker2c1c4822019-10-16 11:02:41 -0700851 /*
Matteo Scandolob85b2f02021-03-18 14:44:41 -0700852 Release alloc/gemport/onu/flow id for given OLT PON interface.
853 :param pon_intf_id: OLT PON interface id
854 :param resource_type: String to identify type of resource
855 :param release_content: required number of ids
856 :return boolean: True if all IDs in given release_content release else False
Scott Baker2c1c4822019-10-16 11:02:41 -0700857 */
Matteo Scandolob85b2f02021-03-18 14:44:41 -0700858
859 logger.Debugw(ctx, "freeing-resource-id", log.Fields{
860 "intf-id": IntfID,
861 "resource-type": ResourceType,
862 "release-content": ReleaseContent,
863 })
864
David K. Bainbridge7c75cac2020-02-19 08:53:46 -0800865 if !checkValidResourceType(ResourceType) {
Matteo Scandolob85b2f02021-03-18 14:44:41 -0700866 err := fmt.Errorf("Invalid resource type: %s", ResourceType)
867 logger.Error(ctx, err.Error())
868 return err
Scott Baker2c1c4822019-10-16 11:02:41 -0700869 }
870 if ReleaseContent == nil {
Matteo Scandolob85b2f02021-03-18 14:44:41 -0700871 err := fmt.Errorf("Nothing to release")
872 logger.Debug(ctx, err.Error())
873 return err
Scott Baker2c1c4822019-10-16 11:02:41 -0700874 }
875 // delegate to the master instance if sharing enabled across instances
876 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
877 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
npujar5bf737f2020-01-16 19:35:25 +0530878 return SharedResourceMgr.FreeResourceID(ctx, IntfID, ResourceType, ReleaseContent)
Scott Baker2c1c4822019-10-16 11:02:41 -0700879 }
Neha Sharma94f16a92020-06-26 04:17:55 +0000880 Path := PONRMgr.GetPath(ctx, IntfID, ResourceType)
Scott Baker2c1c4822019-10-16 11:02:41 -0700881 if Path == "" {
Matteo Scandolob85b2f02021-03-18 14:44:41 -0700882 err := fmt.Errorf("Failed to get path for IntfId %d and ResourceType %s", IntfID, ResourceType)
883 logger.Error(ctx, err.Error())
884 return err
Scott Baker2c1c4822019-10-16 11:02:41 -0700885 }
npujar5bf737f2020-01-16 19:35:25 +0530886 Resource, err := PONRMgr.GetResource(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700887 if err != nil {
Matteo Scandolob85b2f02021-03-18 14:44:41 -0700888 logger.Error(ctx, err.Error())
889 return err
Scott Baker2c1c4822019-10-16 11:02:41 -0700890 }
891 for _, Val := range ReleaseContent {
Neha Sharma94f16a92020-06-26 04:17:55 +0000892 PONRMgr.ReleaseID(ctx, Resource, Val)
Scott Baker2c1c4822019-10-16 11:02:41 -0700893 }
npujar5bf737f2020-01-16 19:35:25 +0530894 if PONRMgr.UpdateResource(ctx, Path, Resource) != nil {
Matteo Scandolob85b2f02021-03-18 14:44:41 -0700895 err := fmt.Errorf("Free resource for %s failed", Path)
896 logger.Errorf(ctx, err.Error())
897 return err
Scott Baker2c1c4822019-10-16 11:02:41 -0700898 }
Matteo Scandolob85b2f02021-03-18 14:44:41 -0700899 return nil
Scott Baker2c1c4822019-10-16 11:02:41 -0700900}
901
npujar5bf737f2020-01-16 19:35:25 +0530902func (PONRMgr *PONResourceManager) UpdateResource(ctx context.Context, Path string, Resource map[string]interface{}) error {
Scott Baker2c1c4822019-10-16 11:02:41 -0700903 /*
904 Update resource in resource kv store.
905 :param path: path to update resource
906 :param resource: resource need to be updated
907 :return boolean: True if resource updated in kv store else False
908 */
909 // TODO resource[POOL] = resource[POOL].bin
910 Value, err := json.Marshal(Resource)
911 if err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000912 logger.Error(ctx, "failed to Marshal")
Scott Baker2c1c4822019-10-16 11:02:41 -0700913 return err
914 }
npujar5bf737f2020-01-16 19:35:25 +0530915 err = PONRMgr.KVStore.Put(ctx, Path, Value)
Scott Baker2c1c4822019-10-16 11:02:41 -0700916 if err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000917 logger.Error(ctx, "failed to put data to kv store %s", Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700918 return err
919 }
920 return nil
921}
922
npujar5bf737f2020-01-16 19:35:25 +0530923func (PONRMgr *PONResourceManager) ClearResourceIDPool(ctx context.Context, contIntfID uint32, ResourceType string) bool {
Scott Baker2c1c4822019-10-16 11:02:41 -0700924 /*
925 Clear Resource Pool for a given Resource Type on a given PON Port.
926 :return boolean: True if removed else False
927 */
928
929 // delegate to the master instance if sharing enabled across instances
930 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
931 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
npujar5bf737f2020-01-16 19:35:25 +0530932 return SharedResourceMgr.ClearResourceIDPool(ctx, contIntfID, ResourceType)
Scott Baker2c1c4822019-10-16 11:02:41 -0700933 }
Neha Sharma94f16a92020-06-26 04:17:55 +0000934 Path := PONRMgr.GetPath(ctx, contIntfID, ResourceType)
Scott Baker2c1c4822019-10-16 11:02:41 -0700935 if Path == "" {
Neha Sharma94f16a92020-06-26 04:17:55 +0000936 logger.Error(ctx, "Failed to get path")
Scott Baker2c1c4822019-10-16 11:02:41 -0700937 return false
938 }
939
npujar5bf737f2020-01-16 19:35:25 +0530940 if err := PONRMgr.KVStore.Delete(ctx, Path); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000941 logger.Errorf(ctx, "Failed to delete resource %s", Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700942 return false
943 }
Neha Sharma94f16a92020-06-26 04:17:55 +0000944 logger.Debugf(ctx, "Cleared resource %s", Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700945 return true
946}
947
npujar5bf737f2020-01-16 19:35:25 +0530948func (PONRMgr PONResourceManager) InitResourceMap(ctx context.Context, PONIntfONUID string) {
Scott Baker2c1c4822019-10-16 11:02:41 -0700949 /*
950 Initialize resource map
951 :param pon_intf_onu_id: reference of PON interface id and onu id
952 */
953 // initialize pon_intf_onu_id tuple to alloc_ids map
954 AllocIDPath := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
955 var AllocIDs []byte
npujar5bf737f2020-01-16 19:35:25 +0530956 Result := PONRMgr.KVStore.Put(ctx, AllocIDPath, AllocIDs)
Scott Baker2c1c4822019-10-16 11:02:41 -0700957 if Result != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000958 logger.Error(ctx, "Failed to update the KV store")
Scott Baker2c1c4822019-10-16 11:02:41 -0700959 return
960 }
961 // initialize pon_intf_onu_id tuple to gemport_ids map
962 GEMPortIDPath := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
963 var GEMPortIDs []byte
npujar5bf737f2020-01-16 19:35:25 +0530964 Result = PONRMgr.KVStore.Put(ctx, GEMPortIDPath, GEMPortIDs)
Scott Baker2c1c4822019-10-16 11:02:41 -0700965 if Result != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000966 logger.Error(ctx, "Failed to update the KV store")
Scott Baker2c1c4822019-10-16 11:02:41 -0700967 return
968 }
969}
970
npujar5bf737f2020-01-16 19:35:25 +0530971func (PONRMgr PONResourceManager) RemoveResourceMap(ctx context.Context, PONIntfONUID string) bool {
Scott Baker2c1c4822019-10-16 11:02:41 -0700972 /*
973 Remove resource map
974 :param pon_intf_onu_id: reference of PON interface id and onu id
975 */
976 // remove pon_intf_onu_id tuple to alloc_ids map
977 var err error
978 AllocIDPath := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
npujar5bf737f2020-01-16 19:35:25 +0530979 if err = PONRMgr.KVStore.Delete(ctx, AllocIDPath); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000980 logger.Errorf(ctx, "Failed to remove resource %s", AllocIDPath)
Scott Baker2c1c4822019-10-16 11:02:41 -0700981 return false
982 }
983 // remove pon_intf_onu_id tuple to gemport_ids map
984 GEMPortIDPath := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
npujar5bf737f2020-01-16 19:35:25 +0530985 err = PONRMgr.KVStore.Delete(ctx, GEMPortIDPath)
Scott Baker2c1c4822019-10-16 11:02:41 -0700986 if err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000987 logger.Errorf(ctx, "Failed to remove resource %s", GEMPortIDPath)
Scott Baker2c1c4822019-10-16 11:02:41 -0700988 return false
989 }
990
991 FlowIDPath := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
npujar5bf737f2020-01-16 19:35:25 +0530992 if FlowIDs, err := PONRMgr.KVStore.List(ctx, FlowIDPath); err != nil {
Scott Baker2c1c4822019-10-16 11:02:41 -0700993 for _, Flow := range FlowIDs {
994 FlowIDInfoPath := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, PONIntfONUID, Flow.Value)
npujar5bf737f2020-01-16 19:35:25 +0530995 if err = PONRMgr.KVStore.Delete(ctx, FlowIDInfoPath); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +0000996 logger.Errorf(ctx, "Failed to remove resource %s", FlowIDInfoPath)
Scott Baker2c1c4822019-10-16 11:02:41 -0700997 return false
998 }
999 }
1000 }
1001
npujar5bf737f2020-01-16 19:35:25 +05301002 if err = PONRMgr.KVStore.Delete(ctx, FlowIDPath); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001003 logger.Errorf(ctx, "Failed to remove resource %s", FlowIDPath)
Scott Baker2c1c4822019-10-16 11:02:41 -07001004 return false
1005 }
1006
1007 return true
1008}
1009
npujar5bf737f2020-01-16 19:35:25 +05301010func (PONRMgr *PONResourceManager) GetCurrentAllocIDForOnu(ctx context.Context, IntfONUID string) []uint32 {
Scott Baker2c1c4822019-10-16 11:02:41 -07001011 /*
1012 Get currently configured alloc ids for given pon_intf_onu_id
1013 :param pon_intf_onu_id: reference of PON interface id and onu id
1014 :return list: List of alloc_ids if available, else None
1015 */
1016 Path := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
1017
1018 var Data []uint32
npujar5bf737f2020-01-16 19:35:25 +05301019 Value, err := PONRMgr.KVStore.Get(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -07001020 if err == nil {
1021 if Value != nil {
1022 Val, err := ToByte(Value.Value)
1023 if err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001024 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"error": err})
Scott Baker2c1c4822019-10-16 11:02:41 -07001025 return Data
1026 }
1027 if err = json.Unmarshal(Val, &Data); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001028 logger.Error(ctx, "Failed to unmarshal", log.Fields{"error": err})
Scott Baker2c1c4822019-10-16 11:02:41 -07001029 return Data
1030 }
1031 }
1032 }
1033 return Data
1034}
1035
npujar5bf737f2020-01-16 19:35:25 +05301036func (PONRMgr *PONResourceManager) GetCurrentGEMPortIDsForOnu(ctx context.Context, IntfONUID string) []uint32 {
Scott Baker2c1c4822019-10-16 11:02:41 -07001037 /*
1038 Get currently configured gemport ids for given pon_intf_onu_id
1039 :param pon_intf_onu_id: reference of PON interface id and onu id
1040 :return list: List of gemport IDs if available, else None
1041 */
1042
1043 Path := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
Neha Sharma94f16a92020-06-26 04:17:55 +00001044 logger.Debugf(ctx, "Getting current gemports for %s", Path)
Scott Baker2c1c4822019-10-16 11:02:41 -07001045 var Data []uint32
npujar5bf737f2020-01-16 19:35:25 +05301046 Value, err := PONRMgr.KVStore.Get(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -07001047 if err == nil {
1048 if Value != nil {
1049 Val, _ := ToByte(Value.Value)
1050 if err = json.Unmarshal(Val, &Data); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001051 logger.Errorw(ctx, "Failed to unmarshal", log.Fields{"error": err})
Scott Baker2c1c4822019-10-16 11:02:41 -07001052 return Data
1053 }
1054 }
1055 } else {
Neha Sharma94f16a92020-06-26 04:17:55 +00001056 logger.Errorf(ctx, "Failed to get data from kvstore for %s", Path)
Scott Baker2c1c4822019-10-16 11:02:41 -07001057 }
1058 return Data
1059}
1060
npujar5bf737f2020-01-16 19:35:25 +05301061func (PONRMgr *PONResourceManager) GetCurrentFlowIDsForOnu(ctx context.Context, IntfONUID string) []uint32 {
Scott Baker2c1c4822019-10-16 11:02:41 -07001062 /*
1063 Get currently configured flow ids for given pon_intf_onu_id
1064 :param pon_intf_onu_id: reference of PON interface id and onu id
1065 :return list: List of Flow IDs if available, else None
1066 */
1067
1068 Path := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
1069
1070 var Data []uint32
npujar5bf737f2020-01-16 19:35:25 +05301071 Value, err := PONRMgr.KVStore.Get(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -07001072 if err == nil {
1073 if Value != nil {
1074 Val, _ := ToByte(Value.Value)
1075 if err = json.Unmarshal(Val, &Data); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001076 logger.Error(ctx, "Failed to unmarshal")
Scott Baker2c1c4822019-10-16 11:02:41 -07001077 return Data
1078 }
1079 }
1080 }
1081 return Data
1082}
1083
npujar5bf737f2020-01-16 19:35:25 +05301084func (PONRMgr *PONResourceManager) GetFlowIDInfo(ctx context.Context, IntfONUID string, FlowID uint32, Data interface{}) error {
Scott Baker2c1c4822019-10-16 11:02:41 -07001085 /*
1086 Get flow details configured for the ONU.
1087 :param pon_intf_onu_id: reference of PON interface id and onu id
1088 :param flow_id: Flow Id reference
1089 :param Data: Result
1090 :return error: nil if no error in getting from KV store
1091 */
1092
1093 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
1094
npujar5bf737f2020-01-16 19:35:25 +05301095 Value, err := PONRMgr.KVStore.Get(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -07001096 if err == nil {
1097 if Value != nil {
1098 Val, err := ToByte(Value.Value)
1099 if err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001100 logger.Errorw(ctx, "Failed to convert flowinfo into byte array", log.Fields{"error": err})
Scott Baker2c1c4822019-10-16 11:02:41 -07001101 return err
1102 }
1103 if err = json.Unmarshal(Val, Data); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001104 logger.Errorw(ctx, "Failed to unmarshal", log.Fields{"error": err})
Scott Baker2c1c4822019-10-16 11:02:41 -07001105 return err
1106 }
1107 }
1108 }
1109 return err
1110}
1111
npujar5bf737f2020-01-16 19:35:25 +05301112func (PONRMgr *PONResourceManager) RemoveFlowIDInfo(ctx context.Context, IntfONUID string, FlowID uint32) bool {
Scott Baker2c1c4822019-10-16 11:02:41 -07001113 /*
1114 Get flow_id details configured for the ONU.
1115 :param pon_intf_onu_id: reference of PON interface id and onu id
1116 :param flow_id: Flow Id reference
1117 */
1118 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
1119
npujar5bf737f2020-01-16 19:35:25 +05301120 if err := PONRMgr.KVStore.Delete(ctx, Path); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001121 logger.Errorf(ctx, "Falied to remove resource %s", Path)
Scott Baker2c1c4822019-10-16 11:02:41 -07001122 return false
1123 }
1124 return true
1125}
1126
Serkant Uluderya198de902020-11-16 20:29:17 +03001127func (PONRMgr *PONResourceManager) RemoveAllFlowIDInfo(ctx context.Context, IntfONUID string) bool {
1128 /*
1129 Remove flow_id_info details configured for the ONU.
1130 :param pon_intf_onu_id: reference of PON interface id and onu id
1131 */
1132 Path := fmt.Sprintf(FLOW_ID_INFO_PATH_INTF_ONU_PREFIX, PONRMgr.DeviceID, IntfONUID)
1133
1134 if err := PONRMgr.KVStore.DeleteWithPrefix(ctx, Path); err != nil {
1135 logger.Errorf(ctx, "Falied to remove resource %s", Path)
1136 return false
1137 }
1138 return true
1139}
1140
npujar5bf737f2020-01-16 19:35:25 +05301141func (PONRMgr *PONResourceManager) UpdateAllocIdsForOnu(ctx context.Context, IntfONUID string, AllocIDs []uint32) error {
Scott Baker2c1c4822019-10-16 11:02:41 -07001142 /*
1143 Update currently configured alloc ids for given pon_intf_onu_id
1144 :param pon_intf_onu_id: reference of PON interface id and onu id
1145 :param alloc_ids: list of alloc ids
1146 */
1147 var Value []byte
1148 var err error
1149 Path := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
Girish Gowdra823da1d2021-10-28 11:47:53 -07001150 if AllocIDs == nil {
1151 // No more alloc ids associated with the key. Delete the key entirely
1152 if err = PONRMgr.KVStore.Delete(ctx, Path); err != nil {
1153 logger.Errorf(ctx, "Failed to delete key %s", Path)
1154 return err
1155 }
1156 } else {
1157 Value, err = json.Marshal(AllocIDs)
1158 if err != nil {
1159 logger.Error(ctx, "failed to Marshal")
1160 return err
1161 }
Scott Baker2c1c4822019-10-16 11:02:41 -07001162
Girish Gowdra823da1d2021-10-28 11:47:53 -07001163 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
1164 logger.Errorf(ctx, "Failed to update resource %s", Path)
1165 return err
1166 }
Scott Baker2c1c4822019-10-16 11:02:41 -07001167 }
1168 return err
1169}
1170
npujar5bf737f2020-01-16 19:35:25 +05301171func (PONRMgr *PONResourceManager) UpdateGEMPortIDsForOnu(ctx context.Context, IntfONUID string, GEMPortIDs []uint32) error {
Scott Baker2c1c4822019-10-16 11:02:41 -07001172 /*
1173 Update currently configured gemport ids for given pon_intf_onu_id
1174 :param pon_intf_onu_id: reference of PON interface id and onu id
1175 :param gemport_ids: list of gem port ids
1176 */
1177
1178 var Value []byte
1179 var err error
1180 Path := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
Neha Sharma94f16a92020-06-26 04:17:55 +00001181 logger.Debugf(ctx, "Updating gemport ids for %s", Path)
Girish Gowdra823da1d2021-10-28 11:47:53 -07001182 if GEMPortIDs == nil {
1183 // No more gemport ids associated with the key. Delete the key entirely
1184 if err = PONRMgr.KVStore.Delete(ctx, Path); err != nil {
1185 logger.Errorf(ctx, "Failed to delete key %s", Path)
1186 return err
1187 }
1188 } else {
1189 Value, err = json.Marshal(GEMPortIDs)
1190 if err != nil {
1191 logger.Error(ctx, "failed to Marshal")
1192 return err
1193 }
Scott Baker2c1c4822019-10-16 11:02:41 -07001194
Girish Gowdra823da1d2021-10-28 11:47:53 -07001195 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
1196 logger.Errorf(ctx, "Failed to update resource %s", Path)
1197 return err
1198 }
Scott Baker2c1c4822019-10-16 11:02:41 -07001199 }
1200 return err
1201}
1202
1203func checkForFlowIDInList(FlowIDList []uint32, FlowID uint32) (bool, uint32) {
1204 /*
1205 Check for a flow id in a given list of flow IDs.
1206 :param FLowIDList: List of Flow IDs
1207 :param FlowID: Flowd to check in the list
1208 : return true and the index if present false otherwise.
1209 */
1210
David K. Bainbridge7c75cac2020-02-19 08:53:46 -08001211 for idx := range FlowIDList {
Scott Baker2c1c4822019-10-16 11:02:41 -07001212 if FlowID == FlowIDList[idx] {
1213 return true, uint32(idx)
1214 }
1215 }
1216 return false, 0
1217}
1218
npujar5bf737f2020-01-16 19:35:25 +05301219func (PONRMgr *PONResourceManager) UpdateFlowIDForOnu(ctx context.Context, IntfONUID string, FlowID uint32, Add bool) error {
Scott Baker2c1c4822019-10-16 11:02:41 -07001220 /*
1221 Update the flow_id list of the ONU (add or remove flow_id from the list)
1222 :param pon_intf_onu_id: reference of PON interface id and onu id
1223 :param flow_id: flow ID
1224 :param add: Boolean flag to indicate whether the flow_id should be
1225 added or removed from the list. Defaults to adding the flow.
1226 */
1227 var Value []byte
1228 var err error
1229 var RetVal bool
1230 var IDx uint32
1231 Path := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
npujar5bf737f2020-01-16 19:35:25 +05301232 FlowIDs := PONRMgr.GetCurrentFlowIDsForOnu(ctx, IntfONUID)
Scott Baker2c1c4822019-10-16 11:02:41 -07001233
1234 if Add {
David K. Bainbridge7c75cac2020-02-19 08:53:46 -08001235 if RetVal, _ = checkForFlowIDInList(FlowIDs, FlowID); RetVal {
1236 return nil
Scott Baker2c1c4822019-10-16 11:02:41 -07001237 }
1238 FlowIDs = append(FlowIDs, FlowID)
1239 } else {
David K. Bainbridge7c75cac2020-02-19 08:53:46 -08001240 if RetVal, IDx = checkForFlowIDInList(FlowIDs, FlowID); !RetVal {
1241 return nil
Scott Baker2c1c4822019-10-16 11:02:41 -07001242 }
1243 // delete the index and shift
1244 FlowIDs = append(FlowIDs[:IDx], FlowIDs[IDx+1:]...)
1245 }
1246 Value, err = json.Marshal(FlowIDs)
1247 if err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001248 logger.Error(ctx, "Failed to Marshal")
Scott Baker2c1c4822019-10-16 11:02:41 -07001249 return err
1250 }
1251
npujar5bf737f2020-01-16 19:35:25 +05301252 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001253 logger.Errorf(ctx, "Failed to update resource %s", Path)
Scott Baker2c1c4822019-10-16 11:02:41 -07001254 return err
1255 }
1256 return err
1257}
1258
npujar5bf737f2020-01-16 19:35:25 +05301259func (PONRMgr *PONResourceManager) UpdateFlowIDInfoForOnu(ctx context.Context, IntfONUID string, FlowID uint32, FlowData interface{}) error {
Scott Baker2c1c4822019-10-16 11:02:41 -07001260 /*
1261 Update any metadata associated with the flow_id. The flow_data could be json
1262 or any of other data structure. The resource manager doesnt care
1263 :param pon_intf_onu_id: reference of PON interface id and onu id
1264 :param flow_id: Flow ID
1265 :param flow_data: Flow data blob
1266 */
1267 var Value []byte
1268 var err error
1269 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
1270 Value, err = json.Marshal(FlowData)
1271 if err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001272 logger.Error(ctx, "failed to Marshal")
Scott Baker2c1c4822019-10-16 11:02:41 -07001273 return err
1274 }
1275
npujar5bf737f2020-01-16 19:35:25 +05301276 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001277 logger.Errorf(ctx, "Failed to update resource %s", Path)
Scott Baker2c1c4822019-10-16 11:02:41 -07001278 return err
1279 }
1280 return err
1281}
1282
Neha Sharma94f16a92020-06-26 04:17:55 +00001283func (PONRMgr *PONResourceManager) GenerateNextID(ctx context.Context, Resource map[string]interface{}) (uint32, error) {
Scott Baker2c1c4822019-10-16 11:02:41 -07001284 /*
1285 Generate unique id having OFFSET as start
1286 :param resource: resource used to generate ID
1287 :return uint32: generated id
1288 */
1289 ByteArray, err := ToByte(Resource[POOL])
1290 if err != nil {
Scott Baker2c1c4822019-10-16 11:02:41 -07001291 return 0, err
1292 }
1293 Data := bitmap.TSFromData(ByteArray, false)
1294 if Data == nil {
Scott Baker2c1c4822019-10-16 11:02:41 -07001295 return 0, errors.New("Failed to get data from byte array")
1296 }
1297
1298 Len := Data.Len()
1299 var Idx int
1300 for Idx = 0; Idx < Len; Idx++ {
David K. Bainbridge7c75cac2020-02-19 08:53:46 -08001301 if !Data.Get(Idx) {
Scott Baker2c1c4822019-10-16 11:02:41 -07001302 break
1303 }
1304 }
Esin Karamanefab54e2021-10-13 11:11:43 +00001305 if Idx == Len {
1306 return 0, errors.New("resource-exhausted--no-free-id-in-the-pool")
1307 }
Scott Baker2c1c4822019-10-16 11:02:41 -07001308 Data.Set(Idx, true)
1309 res := uint32(Resource[START_IDX].(float64))
1310 Resource[POOL] = Data.Data(false)
Neha Sharma94f16a92020-06-26 04:17:55 +00001311 logger.Debugf(ctx, "Generated ID for %d", (uint32(Idx) + res))
Scott Baker2c1c4822019-10-16 11:02:41 -07001312 return (uint32(Idx) + res), err
1313}
1314
Neha Sharma94f16a92020-06-26 04:17:55 +00001315func (PONRMgr *PONResourceManager) ReleaseID(ctx context.Context, Resource map[string]interface{}, Id uint32) bool {
Scott Baker2c1c4822019-10-16 11:02:41 -07001316 /*
1317 Release unique id having OFFSET as start index.
1318 :param resource: resource used to release ID
1319 :param unique_id: id need to be released
1320 */
1321 ByteArray, err := ToByte(Resource[POOL])
1322 if err != nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001323 logger.Error(ctx, "Failed to convert resource to byte array")
Scott Baker2c1c4822019-10-16 11:02:41 -07001324 return false
1325 }
1326 Data := bitmap.TSFromData(ByteArray, false)
1327 if Data == nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001328 logger.Error(ctx, "Failed to get resource pool")
Scott Baker2c1c4822019-10-16 11:02:41 -07001329 return false
1330 }
David K. Bainbridge7c75cac2020-02-19 08:53:46 -08001331 Idx := Id - uint32(Resource[START_IDX].(float64))
Esin Karamanefab54e2021-10-13 11:11:43 +00001332 if Idx >= uint32(Data.Len()) {
1333 logger.Errorf(ctx, "ID %d is out of the boundaries of the pool", Id)
1334 return false
1335 }
Scott Baker2c1c4822019-10-16 11:02:41 -07001336 Data.Set(int(Idx), false)
1337 Resource[POOL] = Data.Data(false)
1338
1339 return true
1340}
1341
Esin Karaman5351fc52020-02-14 07:45:49 +00001342/* Reserves a unique id in the specified resource pool.
1343:param Resource: resource used to reserve ID
1344:param Id: ID to be reserved
1345*/
Neha Sharma94f16a92020-06-26 04:17:55 +00001346func (PONRMgr *PONResourceManager) reserveID(ctx context.Context, TSData *bitmap.Threadsafe, StartIndex uint32, Id uint32) bool {
Esin Karaman5351fc52020-02-14 07:45:49 +00001347 Data := bitmap.TSFromData(TSData.Data(false), false)
1348 if Data == nil {
Neha Sharma94f16a92020-06-26 04:17:55 +00001349 logger.Error(ctx, "Failed to get resource pool")
Esin Karaman5351fc52020-02-14 07:45:49 +00001350 return false
1351 }
1352 Idx := Id - StartIndex
Esin Karamanefab54e2021-10-13 11:11:43 +00001353 if Idx >= uint32(Data.Len()) {
1354 logger.Errorf(ctx, "Reservation failed. ID %d is out of the boundaries of the pool", Id)
1355 return false
1356 }
Esin Karaman5351fc52020-02-14 07:45:49 +00001357 Data.Set(int(Idx), true)
1358 return true
1359}
1360
Scott Baker2c1c4822019-10-16 11:02:41 -07001361func (PONRMgr *PONResourceManager) GetTechnology() string {
1362 return PONRMgr.Technology
1363}
1364
1365func (PONRMgr *PONResourceManager) GetResourceTypeAllocID() string {
1366 return ALLOC_ID
1367}
1368
1369func (PONRMgr *PONResourceManager) GetResourceTypeGemPortID() string {
1370 return GEMPORT_ID
1371}
1372
Matteo Scandolob85b2f02021-03-18 14:44:41 -07001373func (PONRMgr *PONResourceManager) GetResourceTypeOnuID() string {
1374 return ONU_ID
1375}
1376
Scott Baker2c1c4822019-10-16 11:02:41 -07001377// ToByte converts an interface value to a []byte. The interface should either be of
1378// a string type or []byte. Otherwise, an error is returned.
1379func ToByte(value interface{}) ([]byte, error) {
1380 switch t := value.(type) {
1381 case []byte:
1382 return value.([]byte), nil
1383 case string:
1384 return []byte(value.(string)), nil
1385 default:
1386 return nil, fmt.Errorf("unexpected-type-%T", t)
1387 }
1388}
1389
1390// ToString converts an interface value to a string. The interface should either be of
1391// a string type or []byte. Otherwise, an error is returned.
1392func ToString(value interface{}) (string, error) {
1393 switch t := value.(type) {
1394 case []byte:
1395 return string(value.([]byte)), nil
1396 case string:
1397 return value.(string), nil
1398 default:
1399 return "", fmt.Errorf("unexpected-type-%T", t)
1400 }
1401}