blob: ad6c11157de017fd420963af8d872683900951f6 [file] [log] [blame]
khenaidoo106c61a2021-08-11 18:05:46 -04001/*
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 (
20 "context"
21 "encoding/base64"
22 "encoding/json"
23 "errors"
24 "fmt"
25 "time"
26
27 bitmap "github.com/boljen/go-bitmap"
28 "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"
31)
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
41 //Constants for passing command line arguments
42 OLT_MODEL_ARG = "--olt_model"
43
44 PATH_PREFIX = "%s/resource_manager/{%s}"
45
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 */
54
55 PATH_PREFIX_FOR_CONFIG = "%s/resource_manager/config"
56 /*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
114 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}"
119
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
127 KVSTORE_RETRY_TIMEOUT = 5 * time.Second
128 //Path on the KV store for storing reserved gem ports
129 //Format: reserved_gemport_ids
130 RESERVED_GEMPORT_IDS_PATH = "reserved_gemport_ids"
131)
132
133//type ResourceTypeIndex string
134//type ResourceType string
135
136type PONResourceManager struct {
137 //Implements APIs to initialize/allocate/release alloc/gemport/onu IDs.
138 Technology string
139 DeviceType string
140 DeviceID string
141 Backend string // ETCD only currently
142 Address string // address of the KV store
143 OLTModel string
144 KVStore *db.Backend
145 KVStoreForConfig *db.Backend
146
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
156func 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})
158 switch storeType {
159 case "etcd":
160 return kvstore.NewEtcdClient(ctx, address, timeout, log.WarnLevel)
161 }
162 return nil, errors.New("unsupported-kv-store")
163}
164
165func SetKVClient(ctx context.Context, Technology string, Backend string, Addr string, configClient bool, basePathKvStore string) *db.Backend {
166 // TODO : Make sure direct call to NewBackend is working fine with backend , currently there is some
167 // issue between kv store and backend , core is not calling NewBackend directly
168 kvClient, err := newKVClient(ctx, Backend, Addr, KVSTORE_RETRY_TIMEOUT)
169 if err != nil {
170 logger.Fatalw(ctx, "Failed to init KV client\n", log.Fields{"err": err})
171 return nil
172 }
173
174 var pathPrefix string
175 if configClient {
176 pathPrefix = fmt.Sprintf(PATH_PREFIX_FOR_CONFIG, basePathKvStore)
177 } else {
178 pathPrefix = fmt.Sprintf(PATH_PREFIX, basePathKvStore, Technology)
179 }
180
181 kvbackend := &db.Backend{
182 Client: kvClient,
183 StoreType: Backend,
184 Address: Addr,
185 Timeout: KVSTORE_RETRY_TIMEOUT,
186 PathPrefix: pathPrefix}
187
188 return kvbackend
189}
190
191// NewPONResourceManager creates a new PON resource manager.
192func NewPONResourceManager(ctx context.Context, Technology string, DeviceType string, DeviceID string, Backend string, Address string, basePathKvStore string) (*PONResourceManager, error) {
193 var PONMgr PONResourceManager
194 PONMgr.Technology = Technology
195 PONMgr.DeviceType = DeviceType
196 PONMgr.DeviceID = DeviceID
197 PONMgr.Backend = Backend
198 PONMgr.Address = Address
199 PONMgr.KVStore = SetKVClient(ctx, Technology, Backend, Address, false, basePathKvStore)
200 if PONMgr.KVStore == nil {
201 logger.Error(ctx, "KV Client initilization failed")
202 return nil, errors.New("Failed to init KV client")
203 }
204 // init kv client to read from the config path
205 PONMgr.KVStoreForConfig = SetKVClient(ctx, Technology, Backend, Address, true, basePathKvStore)
206 if PONMgr.KVStoreForConfig == nil {
207 logger.Error(ctx, "KV Config Client initilization failed")
208 return nil, errors.New("Failed to init KV Config client")
209 }
210
211 PONMgr.PonResourceRanges = make(map[string]interface{})
212 PONMgr.SharedResourceMgrs = make(map[string]*PONResourceManager)
213 PONMgr.SharedIdxByType = make(map[string]string)
214 PONMgr.SharedIdxByType[ONU_ID] = ONU_ID_SHARED_IDX
215 PONMgr.SharedIdxByType[ALLOC_ID] = ALLOC_ID_SHARED_IDX
216 PONMgr.SharedIdxByType[GEMPORT_ID] = GEMPORT_ID_SHARED_IDX
217 PONMgr.SharedIdxByType[FLOW_ID] = FLOW_ID_SHARED_IDX
218 PONMgr.IntfIDs = make([]uint32, NUM_OF_PON_INTF)
219 PONMgr.OLTModel = DeviceType
220 return &PONMgr, nil
221}
222
223/*
224 Initialize PON resource ranges with config fetched from kv store.
225 return boolean: True if PON resource ranges initialized else false
226 Try to initialize the PON Resource Ranges from KV store based on the
227 OLT model key, if available
228*/
229
230func (PONRMgr *PONResourceManager) InitResourceRangesFromKVStore(ctx context.Context) bool {
231 //Initialize PON resource ranges with config fetched from kv store.
232 //:return boolean: True if PON resource ranges initialized else false
233 // Try to initialize the PON Resource Ranges from KV store based on the
234 // OLT model key, if available
235 if PONRMgr.OLTModel == "" {
236 logger.Error(ctx, "Failed to get OLT model")
237 return false
238 }
239 Path := fmt.Sprintf(PON_RESOURCE_RANGE_CONFIG_PATH, PONRMgr.OLTModel)
240 //get resource from kv store
241 Result, err := PONRMgr.KVStore.Get(ctx, Path)
242 if err != nil {
243 logger.Debugf(ctx, "Error in fetching resource %s from KV strore", Path)
244 return false
245 }
246 if Result == nil {
247 logger.Debug(ctx, "There may be no resources in the KV store in case of fresh bootup, return true")
248 return false
249 }
250 //update internal ranges from kv ranges. If there are missing
251 // values in the KV profile, continue to use the defaults
252 Value, err := ToByte(Result.Value)
253 if err != nil {
254 logger.Error(ctx, "Failed to convert kvpair to byte string")
255 return false
256 }
257 if err := json.Unmarshal(Value, &PONRMgr.PonResourceRanges); err != nil {
258 logger.Error(ctx, "Failed to Unmarshal json byte")
259 return false
260 }
261 logger.Debug(ctx, "Init resource ranges from kvstore success")
262 return true
263}
264
265func (PONRMgr *PONResourceManager) UpdateRanges(ctx context.Context, StartIDx string, StartID uint32, EndIDx string, EndID uint32,
266 SharedIDx string, SharedPoolID uint32, RMgr *PONResourceManager) {
267 /*
268 Update the ranges for all reosurce type in the intermnal maps
269 param: resource type start index
270 param: start ID
271 param: resource type end index
272 param: end ID
273 param: resource type shared index
274 param: shared pool id
275 param: global resource manager
276 */
277 logger.Debugf(ctx, "update ranges for %s, %d", StartIDx, StartID)
278
279 if StartID != 0 {
280 if (PONRMgr.PonResourceRanges[StartIDx] == nil) || (PONRMgr.PonResourceRanges[StartIDx].(uint32) < StartID) {
281 PONRMgr.PonResourceRanges[StartIDx] = StartID
282 }
283 }
284 if EndID != 0 {
285 if (PONRMgr.PonResourceRanges[EndIDx] == nil) || (PONRMgr.PonResourceRanges[EndIDx].(uint32) > EndID) {
286 PONRMgr.PonResourceRanges[EndIDx] = EndID
287 }
288 }
289 //if SharedPoolID != 0 {
290 PONRMgr.PonResourceRanges[SharedIDx] = SharedPoolID
291 //}
292 if RMgr != nil {
293 PONRMgr.SharedResourceMgrs[SharedIDx] = RMgr
294 }
295}
296
297func (PONRMgr *PONResourceManager) InitDefaultPONResourceRanges(ctx context.Context,
298 ONUIDStart uint32,
299 ONUIDEnd uint32,
300 ONUIDSharedPoolID uint32,
301 AllocIDStart uint32,
302 AllocIDEnd uint32,
303 AllocIDSharedPoolID uint32,
304 GEMPortIDStart uint32,
305 GEMPortIDEnd uint32,
306 GEMPortIDSharedPoolID uint32,
307 FlowIDStart uint32,
308 FlowIDEnd uint32,
309 FlowIDSharedPoolID uint32,
310 UNIIDStart uint32,
311 UNIIDEnd uint32,
312 NoOfPONPorts uint32,
313 IntfIDs []uint32) bool {
314
315 /*Initialize default PON resource ranges
316
317 :param onu_id_start_idx: onu id start index
318 :param onu_id_end_idx: onu id end index
319 :param onu_id_shared_pool_id: pool idx for id shared by all intfs or None for no sharing
320 :param alloc_id_start_idx: alloc id start index
321 :param alloc_id_end_idx: alloc id end index
322 :param alloc_id_shared_pool_id: pool idx for alloc id shared by all intfs or None for no sharing
323 :param gemport_id_start_idx: gemport id start index
324 :param gemport_id_end_idx: gemport id end index
325 :param gemport_id_shared_pool_id: pool idx for gemport id shared by all intfs or None for no sharing
326 :param flow_id_start_idx: flow id start index
327 :param flow_id_end_idx: flow id end index
328 :param flow_id_shared_pool_id: pool idx for flow id shared by all intfs or None for no sharing
329 :param num_of_pon_ports: number of PON ports
330 :param intf_ids: interfaces serviced by this manager
331 */
332 PONRMgr.UpdateRanges(ctx, ONU_ID_START_IDX, ONUIDStart, ONU_ID_END_IDX, ONUIDEnd, ONU_ID_SHARED_IDX, ONUIDSharedPoolID, nil)
333 PONRMgr.UpdateRanges(ctx, ALLOC_ID_START_IDX, AllocIDStart, ALLOC_ID_END_IDX, AllocIDEnd, ALLOC_ID_SHARED_IDX, AllocIDSharedPoolID, nil)
334 PONRMgr.UpdateRanges(ctx, GEMPORT_ID_START_IDX, GEMPortIDStart, GEMPORT_ID_END_IDX, GEMPortIDEnd, GEMPORT_ID_SHARED_IDX, GEMPortIDSharedPoolID, nil)
335 PONRMgr.UpdateRanges(ctx, FLOW_ID_START_IDX, FlowIDStart, FLOW_ID_END_IDX, FlowIDEnd, FLOW_ID_SHARED_IDX, FlowIDSharedPoolID, nil)
336 PONRMgr.UpdateRanges(ctx, UNI_ID_START_IDX, UNIIDStart, UNI_ID_END_IDX, UNIIDEnd, "", 0, nil)
337 logger.Debug(ctx, "Initialize default range values")
338 var i uint32
339 if IntfIDs == nil {
340 for i = 0; i < NoOfPONPorts; i++ {
341 PONRMgr.IntfIDs = append(PONRMgr.IntfIDs, i)
342 }
343 } else {
344 PONRMgr.IntfIDs = IntfIDs
345 }
346 return true
347}
348
349func (PONRMgr *PONResourceManager) InitDeviceResourcePool(ctx context.Context) error {
350
351 //Initialize resource pool for all PON ports.
352
353 logger.Debug(ctx, "Init resource ranges")
354
355 var err error
356 for _, Intf := range PONRMgr.IntfIDs {
357 SharedPoolID := PONRMgr.PonResourceRanges[ONU_ID_SHARED_IDX].(uint32)
358 if SharedPoolID != 0 {
359 Intf = SharedPoolID
360 }
361 if err = PONRMgr.InitResourceIDPool(ctx, Intf, ONU_ID,
362 PONRMgr.PonResourceRanges[ONU_ID_START_IDX].(uint32),
363 PONRMgr.PonResourceRanges[ONU_ID_END_IDX].(uint32)); err != nil {
364 logger.Error(ctx, "Failed to init ONU ID resource pool")
365 return err
366 }
367 if SharedPoolID != 0 {
368 break
369 }
370 }
371
372 for _, Intf := range PONRMgr.IntfIDs {
373 SharedPoolID := PONRMgr.PonResourceRanges[ALLOC_ID_SHARED_IDX].(uint32)
374 if SharedPoolID != 0 {
375 Intf = SharedPoolID
376 }
377 if err = PONRMgr.InitResourceIDPool(ctx, Intf, ALLOC_ID,
378 PONRMgr.PonResourceRanges[ALLOC_ID_START_IDX].(uint32),
379 PONRMgr.PonResourceRanges[ALLOC_ID_END_IDX].(uint32)); err != nil {
380 logger.Error(ctx, "Failed to init ALLOC ID resource pool ")
381 return err
382 }
383 if SharedPoolID != 0 {
384 break
385 }
386 }
387 for _, Intf := range PONRMgr.IntfIDs {
388 SharedPoolID := PONRMgr.PonResourceRanges[GEMPORT_ID_SHARED_IDX].(uint32)
389 if SharedPoolID != 0 {
390 Intf = SharedPoolID
391 }
392 if err = PONRMgr.InitResourceIDPool(ctx, Intf, GEMPORT_ID,
393 PONRMgr.PonResourceRanges[GEMPORT_ID_START_IDX].(uint32),
394 PONRMgr.PonResourceRanges[GEMPORT_ID_END_IDX].(uint32)); err != nil {
395 logger.Error(ctx, "Failed to init GEMPORT ID resource pool")
396 return err
397 }
398 if SharedPoolID != 0 {
399 break
400 }
401 }
402
403 for _, Intf := range PONRMgr.IntfIDs {
404 SharedPoolID := PONRMgr.PonResourceRanges[FLOW_ID_SHARED_IDX].(uint32)
405 if SharedPoolID != 0 {
406 Intf = SharedPoolID
407 }
408 if err = PONRMgr.InitResourceIDPool(ctx, Intf, FLOW_ID,
409 PONRMgr.PonResourceRanges[FLOW_ID_START_IDX].(uint32),
410 PONRMgr.PonResourceRanges[FLOW_ID_END_IDX].(uint32)); err != nil {
411 logger.Error(ctx, "Failed to init FLOW ID resource pool")
412 return err
413 }
414 if SharedPoolID != 0 {
415 break
416 }
417 }
418 return err
419}
420
421func (PONRMgr *PONResourceManager) InitDeviceResourcePoolForIntf(ctx context.Context, intfID uint32) error {
422
423 logger.Debug(ctx, "Init resource ranges for intf %d", intfID)
424
425 var err error
426
427 if err = PONRMgr.InitResourceIDPool(ctx, intfID, ONU_ID,
428 PONRMgr.PonResourceRanges[ONU_ID_START_IDX].(uint32),
429 PONRMgr.PonResourceRanges[ONU_ID_END_IDX].(uint32)); err != nil {
430 logger.Error(ctx, "Failed to init ONU ID resource pool")
431 return err
432 }
433
434 if err = PONRMgr.InitResourceIDPool(ctx, intfID, ALLOC_ID,
435 PONRMgr.PonResourceRanges[ALLOC_ID_START_IDX].(uint32),
436 PONRMgr.PonResourceRanges[ALLOC_ID_END_IDX].(uint32)); err != nil {
437 logger.Error(ctx, "Failed to init ALLOC ID resource pool ")
438 return err
439 }
440
441 if err = PONRMgr.InitResourceIDPool(ctx, intfID, GEMPORT_ID,
442 PONRMgr.PonResourceRanges[GEMPORT_ID_START_IDX].(uint32),
443 PONRMgr.PonResourceRanges[GEMPORT_ID_END_IDX].(uint32)); err != nil {
444 logger.Error(ctx, "Failed to init GEMPORT ID resource pool")
445 return err
446 }
447
448 if err = PONRMgr.InitResourceIDPool(ctx, intfID, FLOW_ID,
449 PONRMgr.PonResourceRanges[FLOW_ID_START_IDX].(uint32),
450 PONRMgr.PonResourceRanges[FLOW_ID_END_IDX].(uint32)); err != nil {
451 logger.Error(ctx, "Failed to init FLOW ID resource pool")
452 return err
453 }
454
455 return nil
456}
457
458func (PONRMgr *PONResourceManager) ClearDeviceResourcePool(ctx context.Context) error {
459
460 //Clear resource pool for all PON ports.
461
462 logger.Debug(ctx, "Clear resource ranges")
463
464 for _, Intf := range PONRMgr.IntfIDs {
465 SharedPoolID := PONRMgr.PonResourceRanges[ONU_ID_SHARED_IDX].(uint32)
466 if SharedPoolID != 0 {
467 Intf = SharedPoolID
468 }
469 if status := PONRMgr.ClearResourceIDPool(ctx, Intf, ONU_ID); !status {
470 logger.Error(ctx, "Failed to clear ONU ID resource pool")
471 return errors.New("Failed to clear ONU ID resource pool")
472 }
473 if SharedPoolID != 0 {
474 break
475 }
476 }
477
478 for _, Intf := range PONRMgr.IntfIDs {
479 SharedPoolID := PONRMgr.PonResourceRanges[ALLOC_ID_SHARED_IDX].(uint32)
480 if SharedPoolID != 0 {
481 Intf = SharedPoolID
482 }
483 if status := PONRMgr.ClearResourceIDPool(ctx, Intf, ALLOC_ID); !status {
484 logger.Error(ctx, "Failed to clear ALLOC ID resource pool ")
485 return errors.New("Failed to clear ALLOC ID resource pool")
486 }
487 if SharedPoolID != 0 {
488 break
489 }
490 }
491 for _, Intf := range PONRMgr.IntfIDs {
492 SharedPoolID := PONRMgr.PonResourceRanges[GEMPORT_ID_SHARED_IDX].(uint32)
493 if SharedPoolID != 0 {
494 Intf = SharedPoolID
495 }
496 if status := PONRMgr.ClearResourceIDPool(ctx, Intf, GEMPORT_ID); !status {
497 logger.Error(ctx, "Failed to clear GEMPORT ID resource pool")
498 return errors.New("Failed to clear GEMPORT ID resource pool")
499 }
500 if SharedPoolID != 0 {
501 break
502 }
503 }
504
505 for _, Intf := range PONRMgr.IntfIDs {
506 SharedPoolID := PONRMgr.PonResourceRanges[FLOW_ID_SHARED_IDX].(uint32)
507 if SharedPoolID != 0 {
508 Intf = SharedPoolID
509 }
510 if status := PONRMgr.ClearResourceIDPool(ctx, Intf, FLOW_ID); !status {
511 logger.Error(ctx, "Failed to clear FLOW ID resource pool")
512 return errors.New("Failed to clear FLOW ID resource pool")
513 }
514 if SharedPoolID != 0 {
515 break
516 }
517 }
518 return nil
519}
520
521func (PONRMgr *PONResourceManager) ClearDeviceResourcePoolForIntf(ctx context.Context, intfID uint32) error {
522
523 logger.Debugf(ctx, "Clear resource ranges for intf %d", intfID)
524
525 if status := PONRMgr.ClearResourceIDPool(ctx, intfID, ONU_ID); !status {
526 logger.Error(ctx, "Failed to clear ONU ID resource pool")
527 return errors.New("Failed to clear ONU ID resource pool")
528 }
529
530 if status := PONRMgr.ClearResourceIDPool(ctx, intfID, ALLOC_ID); !status {
531 logger.Error(ctx, "Failed to clear ALLOC ID resource pool ")
532 return errors.New("Failed to clear ALLOC ID resource pool")
533 }
534
535 if status := PONRMgr.ClearResourceIDPool(ctx, intfID, GEMPORT_ID); !status {
536 logger.Error(ctx, "Failed to clear GEMPORT ID resource pool")
537 return errors.New("Failed to clear GEMPORT ID resource pool")
538 }
539
540 if status := PONRMgr.ClearResourceIDPool(ctx, intfID, FLOW_ID); !status {
541 logger.Error(ctx, "Failed to clear FLOW ID resource pool")
542 return errors.New("Failed to clear FLOW ID resource pool")
543 }
544
545 return nil
546}
547
548func (PONRMgr *PONResourceManager) InitResourceIDPool(ctx context.Context, Intf uint32, ResourceType string, StartID uint32, EndID uint32) error {
549
550 /*Initialize Resource ID pool for a given Resource Type on a given PON Port
551
552 :param pon_intf_id: OLT PON interface id
553 :param resource_type: String to identify type of resource
554 :param start_idx: start index for onu id pool
555 :param end_idx: end index for onu id pool
556 :return boolean: True if resource id pool initialized else false
557 */
558
559 // delegate to the master instance if sharing enabled across instances
560 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
561 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
562 return SharedResourceMgr.InitResourceIDPool(ctx, Intf, ResourceType, StartID, EndID)
563 }
564
565 Path := PONRMgr.GetPath(ctx, Intf, ResourceType)
566 if Path == "" {
567 logger.Errorf(ctx, "Failed to get path for resource type %s", ResourceType)
568 return fmt.Errorf("Failed to get path for resource type %s", ResourceType)
569 }
570
571 //In case of adapter reboot and reconciliation resource in kv store
572 //checked for its presence if not kv store update happens
573 Res, err := PONRMgr.GetResource(ctx, Path)
574 if (err == nil) && (Res != nil) {
575 logger.Debugf(ctx, "Resource %s already present in store ", Path)
576 return nil
577 } else {
578 var excluded []uint32
579 if ResourceType == GEMPORT_ID {
580 //get gem port ids defined in the KV store, if any, and exclude them from the gem port id pool
581 if reservedGemPortIds, defined := PONRMgr.getReservedGemPortIdsFromKVStore(ctx); defined {
582 excluded = reservedGemPortIds
583 logger.Debugw(ctx, "Excluding some ports from GEM port id pool", log.Fields{"excluded gem ports": excluded})
584 }
585 }
586 FormatResult, err := PONRMgr.FormatResource(ctx, Intf, StartID, EndID, excluded)
587 if err != nil {
588 logger.Errorf(ctx, "Failed to format resource")
589 return err
590 }
591 // Add resource as json in kv store.
592 err = PONRMgr.KVStore.Put(ctx, Path, FormatResult)
593 if err == nil {
594 logger.Debug(ctx, "Successfuly posted to kv store")
595 return err
596 }
597 }
598
599 logger.Debug(ctx, "Error initializing pool")
600
601 return err
602}
603
604func (PONRMgr *PONResourceManager) getReservedGemPortIdsFromKVStore(ctx context.Context) ([]uint32, bool) {
605 var reservedGemPortIds []uint32
606 // read reserved gem ports from the config path
607 KvPair, err := PONRMgr.KVStoreForConfig.Get(ctx, RESERVED_GEMPORT_IDS_PATH)
608 if err != nil {
609 logger.Errorw(ctx, "Unable to get reserved GEM port ids from the kv store", log.Fields{"err": err})
610 return reservedGemPortIds, false
611 }
612 if KvPair == nil || KvPair.Value == nil {
613 //no reserved gem port defined in the store
614 return reservedGemPortIds, false
615 }
616 Val, err := kvstore.ToByte(KvPair.Value)
617 if err != nil {
618 logger.Errorw(ctx, "Failed to convert reserved gem port ids into byte array", log.Fields{"err": err})
619 return reservedGemPortIds, false
620 }
621 if err = json.Unmarshal(Val, &reservedGemPortIds); err != nil {
622 logger.Errorw(ctx, "Failed to unmarshal reservedGemPortIds", log.Fields{"err": err})
623 return reservedGemPortIds, false
624 }
625 return reservedGemPortIds, true
626}
627
628func (PONRMgr *PONResourceManager) FormatResource(ctx context.Context, IntfID uint32, StartIDx uint32, EndIDx uint32,
629 Excluded []uint32) ([]byte, error) {
630 /*
631 Format resource as json.
632 :param pon_intf_id: OLT PON interface id
633 :param start_idx: start index for id pool
634 :param end_idx: end index for id pool
635 :Id values to be Excluded from the pool
636 :return dictionary: resource formatted as map
637 */
638 // Format resource as json to be stored in backend store
639 Resource := make(map[string]interface{})
640 Resource[PON_INTF_ID] = IntfID
641 Resource[START_IDX] = StartIDx
642 Resource[END_IDX] = EndIDx
643 /*
644 Resource pool stored in backend store as binary string.
645 Tracking the resource allocation will be done by setting the bits \
646 in the byte array. The index set will be the resource number allocated.
647 */
648 var TSData *bitmap.Threadsafe
649 if TSData = bitmap.NewTS(int(EndIDx)); TSData == nil {
650 logger.Error(ctx, "Failed to create a bitmap")
651 return nil, errors.New("Failed to create bitmap")
652 }
653 for _, excludedID := range Excluded {
654 if excludedID < StartIDx || excludedID > EndIDx {
655 logger.Warnf(ctx, "Cannot reserve %d. It must be in the range of [%d, %d]", excludedID,
656 StartIDx, EndIDx)
657 continue
658 }
659 PONRMgr.reserveID(ctx, TSData, StartIDx, excludedID)
660 }
661 Resource[POOL] = TSData.Data(false) //we pass false so as the TSData lib api does not do a copy of the data and return
662
663 Value, err := json.Marshal(Resource)
664 if err != nil {
665 logger.Errorf(ctx, "Failed to marshall resource")
666 return nil, err
667 }
668 return Value, err
669}
670func (PONRMgr *PONResourceManager) GetResource(ctx context.Context, Path string) (map[string]interface{}, error) {
671 /*
672 Get resource from kv store.
673
674 :param path: path to get resource
675 :return: resource if resource present in kv store else None
676 */
677 //get resource from kv store
678
679 var Value []byte
680 Result := make(map[string]interface{})
681 var Str string
682
683 Resource, err := PONRMgr.KVStore.Get(ctx, Path)
684 if (err != nil) || (Resource == nil) {
685 logger.Debugf(ctx, "Resource unavailable at %s", Path)
686 return nil, err
687 }
688
689 Value, err = ToByte(Resource.Value)
690 if err != nil {
691 return nil, err
692 }
693
694 // decode resource fetched from backend store to dictionary
695 err = json.Unmarshal(Value, &Result)
696 if err != nil {
697 logger.Error(ctx, "Failed to decode resource")
698 return Result, err
699 }
700 /*
701 resource pool in backend store stored as binary string whereas to
702 access the pool to generate/release IDs it need to be converted
703 as BitArray
704 */
705 Str, err = ToString(Result[POOL])
706 if err != nil {
707 logger.Error(ctx, "Failed to conver to kv pair to string")
708 return Result, err
709 }
710 Decode64, _ := base64.StdEncoding.DecodeString(Str)
711 Result[POOL], err = ToByte(Decode64)
712 if err != nil {
713 logger.Error(ctx, "Failed to convert resource pool to byte")
714 return Result, err
715 }
716
717 return Result, err
718}
719
720func (PONRMgr *PONResourceManager) GetPath(ctx context.Context, IntfID uint32, ResourceType string) string {
721 /*
722 Get path for given resource type.
723 :param pon_intf_id: OLT PON interface id
724 :param resource_type: String to identify type of resource
725 :return: path for given resource type
726 */
727
728 /*
729 Get the shared pool for the given resource type.
730 all the resource ranges and the shared resource maps are initialized during the init.
731 */
732 SharedPoolID := PONRMgr.PonResourceRanges[PONRMgr.SharedIdxByType[ResourceType]].(uint32)
733 if SharedPoolID != 0 {
734 IntfID = SharedPoolID
735 }
736 var Path string
737 if ResourceType == ONU_ID {
738 Path = fmt.Sprintf(ONU_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
739 } else if ResourceType == ALLOC_ID {
740 Path = fmt.Sprintf(ALLOC_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
741 } else if ResourceType == GEMPORT_ID {
742 Path = fmt.Sprintf(GEMPORT_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
743 } else if ResourceType == FLOW_ID {
744 Path = fmt.Sprintf(FLOW_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
745 } else {
746 logger.Error(ctx, "Invalid resource pool identifier")
747 }
748 return Path
749}
750
751func (PONRMgr *PONResourceManager) GetResourceID(ctx context.Context, IntfID uint32, ResourceType string, NumIDs uint32) ([]uint32, error) {
752 /*
753 Create alloc/gemport/onu/flow id for given OLT PON interface.
754 :param pon_intf_id: OLT PON interface id
755 :param resource_type: String to identify type of resource
756 :param num_of_id: required number of ids
757 :return list/uint32/None: list, uint32 or None if resource type is
758 alloc_id/gemport_id, onu_id or invalid type respectively
759 */
760
761 logger.Debugw(ctx, "getting-resource-id", log.Fields{
762 "intf-id": IntfID,
763 "resource-type": ResourceType,
764 "num": NumIDs,
765 })
766
767 if NumIDs < 1 {
768 logger.Error(ctx, "Invalid number of resources requested")
769 return nil, fmt.Errorf("Invalid number of resources requested %d", NumIDs)
770 }
771 // delegate to the master instance if sharing enabled across instances
772
773 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
774 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
775 return SharedResourceMgr.GetResourceID(ctx, IntfID, ResourceType, NumIDs)
776 }
777 logger.Debugf(ctx, "Fetching resource from %s rsrc mgr for resource %s", PONRMgr.Globalorlocal, ResourceType)
778
779 Path := PONRMgr.GetPath(ctx, IntfID, ResourceType)
780 if Path == "" {
781 logger.Errorf(ctx, "Failed to get path for resource type %s", ResourceType)
782 return nil, fmt.Errorf("Failed to get path for resource type %s", ResourceType)
783 }
784 logger.Debugf(ctx, "Get resource for type %s on path %s", ResourceType, Path)
785 var Result []uint32
786 var NextID uint32
787 Resource, err := PONRMgr.GetResource(ctx, Path)
788 if (err == nil) && (ResourceType == ONU_ID) || (ResourceType == FLOW_ID) {
789 if NextID, err = PONRMgr.GenerateNextID(ctx, Resource); err != nil {
790 logger.Error(ctx, "Failed to Generate ID")
791 return Result, err
792 }
793 Result = append(Result, NextID)
794 } else if (err == nil) && ((ResourceType == GEMPORT_ID) || (ResourceType == ALLOC_ID)) {
795 if NumIDs == 1 {
796 if NextID, err = PONRMgr.GenerateNextID(ctx, Resource); err != nil {
797 logger.Error(ctx, "Failed to Generate ID")
798 return Result, err
799 }
800 Result = append(Result, NextID)
801 } else {
802 for NumIDs > 0 {
803 if NextID, err = PONRMgr.GenerateNextID(ctx, Resource); err != nil {
804 logger.Error(ctx, "Failed to Generate ID")
805 return Result, err
806 }
807 Result = append(Result, NextID)
808 NumIDs--
809 }
810 }
811 } else {
812 logger.Error(ctx, "get resource failed")
813 return Result, err
814 }
815
816 //Update resource in kv store
817 if PONRMgr.UpdateResource(ctx, Path, Resource) != nil {
818 logger.Errorf(ctx, "Failed to update resource %s", Path)
819 return nil, fmt.Errorf("Failed to update resource %s", Path)
820 }
821 return Result, nil
822}
823
824func checkValidResourceType(ResourceType string) bool {
825 KnownResourceTypes := []string{ONU_ID, ALLOC_ID, GEMPORT_ID, FLOW_ID}
826
827 for _, v := range KnownResourceTypes {
828 if v == ResourceType {
829 return true
830 }
831 }
832 return false
833}
834
835func (PONRMgr *PONResourceManager) FreeResourceID(ctx context.Context, IntfID uint32, ResourceType string, ReleaseContent []uint32) error {
836 /*
837 Release alloc/gemport/onu/flow id for given OLT PON interface.
838 :param pon_intf_id: OLT PON interface id
839 :param resource_type: String to identify type of resource
840 :param release_content: required number of ids
841 :return boolean: True if all IDs in given release_content release else False
842 */
843
844 logger.Debugw(ctx, "freeing-resource-id", log.Fields{
845 "intf-id": IntfID,
846 "resource-type": ResourceType,
847 "release-content": ReleaseContent,
848 })
849
850 if !checkValidResourceType(ResourceType) {
851 err := fmt.Errorf("Invalid resource type: %s", ResourceType)
852 logger.Error(ctx, err.Error())
853 return err
854 }
855 if ReleaseContent == nil {
856 err := fmt.Errorf("Nothing to release")
857 logger.Debug(ctx, err.Error())
858 return err
859 }
860 // delegate to the master instance if sharing enabled across instances
861 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
862 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
863 return SharedResourceMgr.FreeResourceID(ctx, IntfID, ResourceType, ReleaseContent)
864 }
865 Path := PONRMgr.GetPath(ctx, IntfID, ResourceType)
866 if Path == "" {
867 err := fmt.Errorf("Failed to get path for IntfId %d and ResourceType %s", IntfID, ResourceType)
868 logger.Error(ctx, err.Error())
869 return err
870 }
871 Resource, err := PONRMgr.GetResource(ctx, Path)
872 if err != nil {
873 logger.Error(ctx, err.Error())
874 return err
875 }
876 for _, Val := range ReleaseContent {
877 PONRMgr.ReleaseID(ctx, Resource, Val)
878 }
879 if PONRMgr.UpdateResource(ctx, Path, Resource) != nil {
880 err := fmt.Errorf("Free resource for %s failed", Path)
881 logger.Errorf(ctx, err.Error())
882 return err
883 }
884 return nil
885}
886
887func (PONRMgr *PONResourceManager) UpdateResource(ctx context.Context, Path string, Resource map[string]interface{}) error {
888 /*
889 Update resource in resource kv store.
890 :param path: path to update resource
891 :param resource: resource need to be updated
892 :return boolean: True if resource updated in kv store else False
893 */
894 // TODO resource[POOL] = resource[POOL].bin
895 Value, err := json.Marshal(Resource)
896 if err != nil {
897 logger.Error(ctx, "failed to Marshal")
898 return err
899 }
900 err = PONRMgr.KVStore.Put(ctx, Path, Value)
901 if err != nil {
902 logger.Error(ctx, "failed to put data to kv store %s", Path)
903 return err
904 }
905 return nil
906}
907
908func (PONRMgr *PONResourceManager) ClearResourceIDPool(ctx context.Context, contIntfID uint32, ResourceType string) bool {
909 /*
910 Clear Resource Pool for a given Resource Type on a given PON Port.
911 :return boolean: True if removed else False
912 */
913
914 // delegate to the master instance if sharing enabled across instances
915 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
916 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
917 return SharedResourceMgr.ClearResourceIDPool(ctx, contIntfID, ResourceType)
918 }
919 Path := PONRMgr.GetPath(ctx, contIntfID, ResourceType)
920 if Path == "" {
921 logger.Error(ctx, "Failed to get path")
922 return false
923 }
924
925 if err := PONRMgr.KVStore.Delete(ctx, Path); err != nil {
926 logger.Errorf(ctx, "Failed to delete resource %s", Path)
927 return false
928 }
929 logger.Debugf(ctx, "Cleared resource %s", Path)
930 return true
931}
932
933func (PONRMgr PONResourceManager) InitResourceMap(ctx context.Context, PONIntfONUID string) {
934 /*
935 Initialize resource map
936 :param pon_intf_onu_id: reference of PON interface id and onu id
937 */
938 // initialize pon_intf_onu_id tuple to alloc_ids map
939 AllocIDPath := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
940 var AllocIDs []byte
941 Result := PONRMgr.KVStore.Put(ctx, AllocIDPath, AllocIDs)
942 if Result != nil {
943 logger.Error(ctx, "Failed to update the KV store")
944 return
945 }
946 // initialize pon_intf_onu_id tuple to gemport_ids map
947 GEMPortIDPath := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
948 var GEMPortIDs []byte
949 Result = PONRMgr.KVStore.Put(ctx, GEMPortIDPath, GEMPortIDs)
950 if Result != nil {
951 logger.Error(ctx, "Failed to update the KV store")
952 return
953 }
954}
955
956func (PONRMgr PONResourceManager) RemoveResourceMap(ctx context.Context, PONIntfONUID string) bool {
957 /*
958 Remove resource map
959 :param pon_intf_onu_id: reference of PON interface id and onu id
960 */
961 // remove pon_intf_onu_id tuple to alloc_ids map
962 var err error
963 AllocIDPath := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
964 if err = PONRMgr.KVStore.Delete(ctx, AllocIDPath); err != nil {
965 logger.Errorf(ctx, "Failed to remove resource %s", AllocIDPath)
966 return false
967 }
968 // remove pon_intf_onu_id tuple to gemport_ids map
969 GEMPortIDPath := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
970 err = PONRMgr.KVStore.Delete(ctx, GEMPortIDPath)
971 if err != nil {
972 logger.Errorf(ctx, "Failed to remove resource %s", GEMPortIDPath)
973 return false
974 }
975
976 FlowIDPath := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
977 if FlowIDs, err := PONRMgr.KVStore.List(ctx, FlowIDPath); err != nil {
978 for _, Flow := range FlowIDs {
979 FlowIDInfoPath := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, PONIntfONUID, Flow.Value)
980 if err = PONRMgr.KVStore.Delete(ctx, FlowIDInfoPath); err != nil {
981 logger.Errorf(ctx, "Failed to remove resource %s", FlowIDInfoPath)
982 return false
983 }
984 }
985 }
986
987 if err = PONRMgr.KVStore.Delete(ctx, FlowIDPath); err != nil {
988 logger.Errorf(ctx, "Failed to remove resource %s", FlowIDPath)
989 return false
990 }
991
992 return true
993}
994
995func (PONRMgr *PONResourceManager) GetCurrentAllocIDForOnu(ctx context.Context, IntfONUID string) []uint32 {
996 /*
997 Get currently configured alloc ids for given pon_intf_onu_id
998 :param pon_intf_onu_id: reference of PON interface id and onu id
999 :return list: List of alloc_ids if available, else None
1000 */
1001 Path := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
1002
1003 var Data []uint32
1004 Value, err := PONRMgr.KVStore.Get(ctx, Path)
1005 if err == nil {
1006 if Value != nil {
1007 Val, err := ToByte(Value.Value)
1008 if err != nil {
1009 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"error": err})
1010 return Data
1011 }
1012 if err = json.Unmarshal(Val, &Data); err != nil {
1013 logger.Error(ctx, "Failed to unmarshal", log.Fields{"error": err})
1014 return Data
1015 }
1016 }
1017 }
1018 return Data
1019}
1020
1021func (PONRMgr *PONResourceManager) GetCurrentGEMPortIDsForOnu(ctx context.Context, IntfONUID string) []uint32 {
1022 /*
1023 Get currently configured gemport ids for given pon_intf_onu_id
1024 :param pon_intf_onu_id: reference of PON interface id and onu id
1025 :return list: List of gemport IDs if available, else None
1026 */
1027
1028 Path := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
1029 logger.Debugf(ctx, "Getting current gemports for %s", Path)
1030 var Data []uint32
1031 Value, err := PONRMgr.KVStore.Get(ctx, Path)
1032 if err == nil {
1033 if Value != nil {
1034 Val, _ := ToByte(Value.Value)
1035 if err = json.Unmarshal(Val, &Data); err != nil {
1036 logger.Errorw(ctx, "Failed to unmarshal", log.Fields{"error": err})
1037 return Data
1038 }
1039 }
1040 } else {
1041 logger.Errorf(ctx, "Failed to get data from kvstore for %s", Path)
1042 }
1043 return Data
1044}
1045
1046func (PONRMgr *PONResourceManager) GetCurrentFlowIDsForOnu(ctx context.Context, IntfONUID string) []uint32 {
1047 /*
1048 Get currently configured flow ids for given pon_intf_onu_id
1049 :param pon_intf_onu_id: reference of PON interface id and onu id
1050 :return list: List of Flow IDs if available, else None
1051 */
1052
1053 Path := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
1054
1055 var Data []uint32
1056 Value, err := PONRMgr.KVStore.Get(ctx, Path)
1057 if err == nil {
1058 if Value != nil {
1059 Val, _ := ToByte(Value.Value)
1060 if err = json.Unmarshal(Val, &Data); err != nil {
1061 logger.Error(ctx, "Failed to unmarshal")
1062 return Data
1063 }
1064 }
1065 }
1066 return Data
1067}
1068
1069func (PONRMgr *PONResourceManager) GetFlowIDInfo(ctx context.Context, IntfONUID string, FlowID uint32, Data interface{}) error {
1070 /*
1071 Get flow details configured for the ONU.
1072 :param pon_intf_onu_id: reference of PON interface id and onu id
1073 :param flow_id: Flow Id reference
1074 :param Data: Result
1075 :return error: nil if no error in getting from KV store
1076 */
1077
1078 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
1079
1080 Value, err := PONRMgr.KVStore.Get(ctx, Path)
1081 if err == nil {
1082 if Value != nil {
1083 Val, err := ToByte(Value.Value)
1084 if err != nil {
1085 logger.Errorw(ctx, "Failed to convert flowinfo into byte array", log.Fields{"error": err})
1086 return err
1087 }
1088 if err = json.Unmarshal(Val, Data); err != nil {
1089 logger.Errorw(ctx, "Failed to unmarshal", log.Fields{"error": err})
1090 return err
1091 }
1092 }
1093 }
1094 return err
1095}
1096
1097func (PONRMgr *PONResourceManager) RemoveFlowIDInfo(ctx context.Context, IntfONUID string, FlowID uint32) bool {
1098 /*
1099 Get flow_id details configured for the ONU.
1100 :param pon_intf_onu_id: reference of PON interface id and onu id
1101 :param flow_id: Flow Id reference
1102 */
1103 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
1104
1105 if err := PONRMgr.KVStore.Delete(ctx, Path); err != nil {
1106 logger.Errorf(ctx, "Falied to remove resource %s", Path)
1107 return false
1108 }
1109 return true
1110}
1111
1112func (PONRMgr *PONResourceManager) RemoveAllFlowIDInfo(ctx context.Context, IntfONUID string) bool {
1113 /*
1114 Remove flow_id_info details configured for the ONU.
1115 :param pon_intf_onu_id: reference of PON interface id and onu id
1116 */
1117 Path := fmt.Sprintf(FLOW_ID_INFO_PATH_INTF_ONU_PREFIX, PONRMgr.DeviceID, IntfONUID)
1118
1119 if err := PONRMgr.KVStore.DeleteWithPrefix(ctx, Path); err != nil {
1120 logger.Errorf(ctx, "Falied to remove resource %s", Path)
1121 return false
1122 }
1123 return true
1124}
1125
1126func (PONRMgr *PONResourceManager) UpdateAllocIdsForOnu(ctx context.Context, IntfONUID string, AllocIDs []uint32) error {
1127 /*
1128 Update currently configured alloc ids for given pon_intf_onu_id
1129 :param pon_intf_onu_id: reference of PON interface id and onu id
1130 :param alloc_ids: list of alloc ids
1131 */
1132 var Value []byte
1133 var err error
1134 Path := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
Girish Gowdra315a9342021-10-28 11:49:22 -07001135 if AllocIDs == nil {
1136 // No more alloc ids associated with the key. Delete the key entirely
1137 if err = PONRMgr.KVStore.Delete(ctx, Path); err != nil {
1138 logger.Errorf(ctx, "Failed to delete key %s", Path)
1139 return err
1140 }
1141 } else {
1142 Value, err = json.Marshal(AllocIDs)
1143 if err != nil {
1144 logger.Error(ctx, "failed to Marshal")
1145 return err
1146 }
khenaidoo106c61a2021-08-11 18:05:46 -04001147
Girish Gowdra315a9342021-10-28 11:49:22 -07001148 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
1149 logger.Errorf(ctx, "Failed to update resource %s", Path)
1150 return err
1151 }
khenaidoo106c61a2021-08-11 18:05:46 -04001152 }
1153 return err
1154}
1155
1156func (PONRMgr *PONResourceManager) UpdateGEMPortIDsForOnu(ctx context.Context, IntfONUID string, GEMPortIDs []uint32) error {
1157 /*
1158 Update currently configured gemport ids for given pon_intf_onu_id
1159 :param pon_intf_onu_id: reference of PON interface id and onu id
1160 :param gemport_ids: list of gem port ids
1161 */
1162
1163 var Value []byte
1164 var err error
1165 Path := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
1166 logger.Debugf(ctx, "Updating gemport ids for %s", Path)
Girish Gowdra315a9342021-10-28 11:49:22 -07001167 if GEMPortIDs == nil {
1168 // No more gemport ids associated with the key. Delete the key entirely
1169 if err = PONRMgr.KVStore.Delete(ctx, Path); err != nil {
1170 logger.Errorf(ctx, "Failed to delete key %s", Path)
1171 return err
1172 }
1173 } else {
1174 Value, err = json.Marshal(GEMPortIDs)
1175 if err != nil {
1176 logger.Error(ctx, "failed to Marshal")
1177 return err
1178 }
khenaidoo106c61a2021-08-11 18:05:46 -04001179
Girish Gowdra315a9342021-10-28 11:49:22 -07001180 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
1181 logger.Errorf(ctx, "Failed to update resource %s", Path)
1182 return err
1183 }
khenaidoo106c61a2021-08-11 18:05:46 -04001184 }
1185 return err
1186}
1187
1188func checkForFlowIDInList(FlowIDList []uint32, FlowID uint32) (bool, uint32) {
1189 /*
1190 Check for a flow id in a given list of flow IDs.
1191 :param FLowIDList: List of Flow IDs
1192 :param FlowID: Flowd to check in the list
1193 : return true and the index if present false otherwise.
1194 */
1195
1196 for idx := range FlowIDList {
1197 if FlowID == FlowIDList[idx] {
1198 return true, uint32(idx)
1199 }
1200 }
1201 return false, 0
1202}
1203
1204func (PONRMgr *PONResourceManager) UpdateFlowIDForOnu(ctx context.Context, IntfONUID string, FlowID uint32, Add bool) error {
1205 /*
1206 Update the flow_id list of the ONU (add or remove flow_id from the list)
1207 :param pon_intf_onu_id: reference of PON interface id and onu id
1208 :param flow_id: flow ID
1209 :param add: Boolean flag to indicate whether the flow_id should be
1210 added or removed from the list. Defaults to adding the flow.
1211 */
1212 var Value []byte
1213 var err error
1214 var RetVal bool
1215 var IDx uint32
1216 Path := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
1217 FlowIDs := PONRMgr.GetCurrentFlowIDsForOnu(ctx, IntfONUID)
1218
1219 if Add {
1220 if RetVal, _ = checkForFlowIDInList(FlowIDs, FlowID); RetVal {
1221 return nil
1222 }
1223 FlowIDs = append(FlowIDs, FlowID)
1224 } else {
1225 if RetVal, IDx = checkForFlowIDInList(FlowIDs, FlowID); !RetVal {
1226 return nil
1227 }
1228 // delete the index and shift
1229 FlowIDs = append(FlowIDs[:IDx], FlowIDs[IDx+1:]...)
1230 }
1231 Value, err = json.Marshal(FlowIDs)
1232 if err != nil {
1233 logger.Error(ctx, "Failed to Marshal")
1234 return err
1235 }
1236
1237 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
1238 logger.Errorf(ctx, "Failed to update resource %s", Path)
1239 return err
1240 }
1241 return err
1242}
1243
1244func (PONRMgr *PONResourceManager) UpdateFlowIDInfoForOnu(ctx context.Context, IntfONUID string, FlowID uint32, FlowData interface{}) error {
1245 /*
1246 Update any metadata associated with the flow_id. The flow_data could be json
1247 or any of other data structure. The resource manager doesnt care
1248 :param pon_intf_onu_id: reference of PON interface id and onu id
1249 :param flow_id: Flow ID
1250 :param flow_data: Flow data blob
1251 */
1252 var Value []byte
1253 var err error
1254 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
1255 Value, err = json.Marshal(FlowData)
1256 if err != nil {
1257 logger.Error(ctx, "failed to Marshal")
1258 return err
1259 }
1260
1261 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
1262 logger.Errorf(ctx, "Failed to update resource %s", Path)
1263 return err
1264 }
1265 return err
1266}
1267
1268func (PONRMgr *PONResourceManager) GenerateNextID(ctx context.Context, Resource map[string]interface{}) (uint32, error) {
1269 /*
1270 Generate unique id having OFFSET as start
1271 :param resource: resource used to generate ID
1272 :return uint32: generated id
1273 */
1274 ByteArray, err := ToByte(Resource[POOL])
1275 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001276 return 0, err
1277 }
1278 Data := bitmap.TSFromData(ByteArray, false)
1279 if Data == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001280 return 0, errors.New("Failed to get data from byte array")
1281 }
1282
1283 Len := Data.Len()
1284 var Idx int
1285 for Idx = 0; Idx < Len; Idx++ {
1286 if !Data.Get(Idx) {
1287 break
1288 }
1289 }
Girish Gowdra315a9342021-10-28 11:49:22 -07001290 if Idx == Len {
1291 return 0, errors.New("resource-exhausted--no-free-id-in-the-pool")
1292 }
khenaidoo106c61a2021-08-11 18:05:46 -04001293 Data.Set(Idx, true)
1294 res := uint32(Resource[START_IDX].(float64))
1295 Resource[POOL] = Data.Data(false)
1296 logger.Debugf(ctx, "Generated ID for %d", (uint32(Idx) + res))
1297 return (uint32(Idx) + res), err
1298}
1299
1300func (PONRMgr *PONResourceManager) ReleaseID(ctx context.Context, Resource map[string]interface{}, Id uint32) bool {
1301 /*
1302 Release unique id having OFFSET as start index.
1303 :param resource: resource used to release ID
1304 :param unique_id: id need to be released
1305 */
1306 ByteArray, err := ToByte(Resource[POOL])
1307 if err != nil {
1308 logger.Error(ctx, "Failed to convert resource to byte array")
1309 return false
1310 }
1311 Data := bitmap.TSFromData(ByteArray, false)
1312 if Data == nil {
1313 logger.Error(ctx, "Failed to get resource pool")
1314 return false
1315 }
1316 Idx := Id - uint32(Resource[START_IDX].(float64))
Girish Gowdra315a9342021-10-28 11:49:22 -07001317 if Idx >= uint32(Data.Len()) {
1318 logger.Errorf(ctx, "ID %d is out of the boundaries of the pool", Id)
1319 return false
1320 }
khenaidoo106c61a2021-08-11 18:05:46 -04001321 Data.Set(int(Idx), false)
1322 Resource[POOL] = Data.Data(false)
1323
1324 return true
1325}
1326
1327/* Reserves a unique id in the specified resource pool.
1328:param Resource: resource used to reserve ID
1329:param Id: ID to be reserved
1330*/
1331func (PONRMgr *PONResourceManager) reserveID(ctx context.Context, TSData *bitmap.Threadsafe, StartIndex uint32, Id uint32) bool {
1332 Data := bitmap.TSFromData(TSData.Data(false), false)
1333 if Data == nil {
1334 logger.Error(ctx, "Failed to get resource pool")
1335 return false
1336 }
1337 Idx := Id - StartIndex
Girish Gowdra315a9342021-10-28 11:49:22 -07001338 if Idx >= uint32(Data.Len()) {
1339 logger.Errorf(ctx, "Reservation failed. ID %d is out of the boundaries of the pool", Id)
1340 return false
1341 }
khenaidoo106c61a2021-08-11 18:05:46 -04001342 Data.Set(int(Idx), true)
1343 return true
1344}
1345
1346func (PONRMgr *PONResourceManager) GetTechnology() string {
1347 return PONRMgr.Technology
1348}
1349
1350func (PONRMgr *PONResourceManager) GetResourceTypeAllocID() string {
1351 return ALLOC_ID
1352}
1353
1354func (PONRMgr *PONResourceManager) GetResourceTypeGemPortID() string {
1355 return GEMPORT_ID
1356}
1357
1358func (PONRMgr *PONResourceManager) GetResourceTypeOnuID() string {
1359 return ONU_ID
1360}
1361
1362// ToByte converts an interface value to a []byte. The interface should either be of
1363// a string type or []byte. Otherwise, an error is returned.
1364func ToByte(value interface{}) ([]byte, error) {
1365 switch t := value.(type) {
1366 case []byte:
1367 return value.([]byte), nil
1368 case string:
1369 return []byte(value.(string)), nil
1370 default:
1371 return nil, fmt.Errorf("unexpected-type-%T", t)
1372 }
1373}
1374
1375// ToString converts an interface value to a string. The interface should either be of
1376// a string type or []byte. Otherwise, an error is returned.
1377func ToString(value interface{}) (string, error) {
1378 switch t := value.(type) {
1379 case []byte:
1380 return string(value.([]byte)), nil
1381 case string:
1382 return value.(string), nil
1383 default:
1384 return "", fmt.Errorf("unexpected-type-%T", t)
1385 }
1386}