blob: ba67aeb6d0e3514aeaaa3a1015b4a318d18bab0a [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)
1135 Value, err = json.Marshal(AllocIDs)
1136 if err != nil {
1137 logger.Error(ctx, "failed to Marshal")
1138 return err
1139 }
1140
1141 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
1142 logger.Errorf(ctx, "Failed to update resource %s", Path)
1143 return err
1144 }
1145 return err
1146}
1147
1148func (PONRMgr *PONResourceManager) UpdateGEMPortIDsForOnu(ctx context.Context, IntfONUID string, GEMPortIDs []uint32) error {
1149 /*
1150 Update currently configured gemport ids for given pon_intf_onu_id
1151 :param pon_intf_onu_id: reference of PON interface id and onu id
1152 :param gemport_ids: list of gem port ids
1153 */
1154
1155 var Value []byte
1156 var err error
1157 Path := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
1158 logger.Debugf(ctx, "Updating gemport ids for %s", Path)
1159 Value, err = json.Marshal(GEMPortIDs)
1160 if err != nil {
1161 logger.Error(ctx, "failed to Marshal")
1162 return err
1163 }
1164
1165 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
1166 logger.Errorf(ctx, "Failed to update resource %s", Path)
1167 return err
1168 }
1169 return err
1170}
1171
1172func checkForFlowIDInList(FlowIDList []uint32, FlowID uint32) (bool, uint32) {
1173 /*
1174 Check for a flow id in a given list of flow IDs.
1175 :param FLowIDList: List of Flow IDs
1176 :param FlowID: Flowd to check in the list
1177 : return true and the index if present false otherwise.
1178 */
1179
1180 for idx := range FlowIDList {
1181 if FlowID == FlowIDList[idx] {
1182 return true, uint32(idx)
1183 }
1184 }
1185 return false, 0
1186}
1187
1188func (PONRMgr *PONResourceManager) UpdateFlowIDForOnu(ctx context.Context, IntfONUID string, FlowID uint32, Add bool) error {
1189 /*
1190 Update the flow_id list of the ONU (add or remove flow_id from the list)
1191 :param pon_intf_onu_id: reference of PON interface id and onu id
1192 :param flow_id: flow ID
1193 :param add: Boolean flag to indicate whether the flow_id should be
1194 added or removed from the list. Defaults to adding the flow.
1195 */
1196 var Value []byte
1197 var err error
1198 var RetVal bool
1199 var IDx uint32
1200 Path := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
1201 FlowIDs := PONRMgr.GetCurrentFlowIDsForOnu(ctx, IntfONUID)
1202
1203 if Add {
1204 if RetVal, _ = checkForFlowIDInList(FlowIDs, FlowID); RetVal {
1205 return nil
1206 }
1207 FlowIDs = append(FlowIDs, FlowID)
1208 } else {
1209 if RetVal, IDx = checkForFlowIDInList(FlowIDs, FlowID); !RetVal {
1210 return nil
1211 }
1212 // delete the index and shift
1213 FlowIDs = append(FlowIDs[:IDx], FlowIDs[IDx+1:]...)
1214 }
1215 Value, err = json.Marshal(FlowIDs)
1216 if err != nil {
1217 logger.Error(ctx, "Failed to Marshal")
1218 return err
1219 }
1220
1221 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
1222 logger.Errorf(ctx, "Failed to update resource %s", Path)
1223 return err
1224 }
1225 return err
1226}
1227
1228func (PONRMgr *PONResourceManager) UpdateFlowIDInfoForOnu(ctx context.Context, IntfONUID string, FlowID uint32, FlowData interface{}) error {
1229 /*
1230 Update any metadata associated with the flow_id. The flow_data could be json
1231 or any of other data structure. The resource manager doesnt care
1232 :param pon_intf_onu_id: reference of PON interface id and onu id
1233 :param flow_id: Flow ID
1234 :param flow_data: Flow data blob
1235 */
1236 var Value []byte
1237 var err error
1238 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
1239 Value, err = json.Marshal(FlowData)
1240 if err != nil {
1241 logger.Error(ctx, "failed to Marshal")
1242 return err
1243 }
1244
1245 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
1246 logger.Errorf(ctx, "Failed to update resource %s", Path)
1247 return err
1248 }
1249 return err
1250}
1251
1252func (PONRMgr *PONResourceManager) GenerateNextID(ctx context.Context, Resource map[string]interface{}) (uint32, error) {
1253 /*
1254 Generate unique id having OFFSET as start
1255 :param resource: resource used to generate ID
1256 :return uint32: generated id
1257 */
1258 ByteArray, err := ToByte(Resource[POOL])
1259 if err != nil {
1260 logger.Error(ctx, "Failed to convert resource to byte array")
1261 return 0, err
1262 }
1263 Data := bitmap.TSFromData(ByteArray, false)
1264 if Data == nil {
1265 logger.Error(ctx, "Failed to get data from byte array")
1266 return 0, errors.New("Failed to get data from byte array")
1267 }
1268
1269 Len := Data.Len()
1270 var Idx int
1271 for Idx = 0; Idx < Len; Idx++ {
1272 if !Data.Get(Idx) {
1273 break
1274 }
1275 }
1276 Data.Set(Idx, true)
1277 res := uint32(Resource[START_IDX].(float64))
1278 Resource[POOL] = Data.Data(false)
1279 logger.Debugf(ctx, "Generated ID for %d", (uint32(Idx) + res))
1280 return (uint32(Idx) + res), err
1281}
1282
1283func (PONRMgr *PONResourceManager) ReleaseID(ctx context.Context, Resource map[string]interface{}, Id uint32) bool {
1284 /*
1285 Release unique id having OFFSET as start index.
1286 :param resource: resource used to release ID
1287 :param unique_id: id need to be released
1288 */
1289 ByteArray, err := ToByte(Resource[POOL])
1290 if err != nil {
1291 logger.Error(ctx, "Failed to convert resource to byte array")
1292 return false
1293 }
1294 Data := bitmap.TSFromData(ByteArray, false)
1295 if Data == nil {
1296 logger.Error(ctx, "Failed to get resource pool")
1297 return false
1298 }
1299 Idx := Id - uint32(Resource[START_IDX].(float64))
1300 Data.Set(int(Idx), false)
1301 Resource[POOL] = Data.Data(false)
1302
1303 return true
1304}
1305
1306/* Reserves a unique id in the specified resource pool.
1307:param Resource: resource used to reserve ID
1308:param Id: ID to be reserved
1309*/
1310func (PONRMgr *PONResourceManager) reserveID(ctx context.Context, TSData *bitmap.Threadsafe, StartIndex uint32, Id uint32) bool {
1311 Data := bitmap.TSFromData(TSData.Data(false), false)
1312 if Data == nil {
1313 logger.Error(ctx, "Failed to get resource pool")
1314 return false
1315 }
1316 Idx := Id - StartIndex
1317 Data.Set(int(Idx), true)
1318 return true
1319}
1320
1321func (PONRMgr *PONResourceManager) GetTechnology() string {
1322 return PONRMgr.Technology
1323}
1324
1325func (PONRMgr *PONResourceManager) GetResourceTypeAllocID() string {
1326 return ALLOC_ID
1327}
1328
1329func (PONRMgr *PONResourceManager) GetResourceTypeGemPortID() string {
1330 return GEMPORT_ID
1331}
1332
1333func (PONRMgr *PONResourceManager) GetResourceTypeOnuID() string {
1334 return ONU_ID
1335}
1336
1337// ToByte converts an interface value to a []byte. The interface should either be of
1338// a string type or []byte. Otherwise, an error is returned.
1339func ToByte(value interface{}) ([]byte, error) {
1340 switch t := value.(type) {
1341 case []byte:
1342 return value.([]byte), nil
1343 case string:
1344 return []byte(value.(string)), nil
1345 default:
1346 return nil, fmt.Errorf("unexpected-type-%T", t)
1347 }
1348}
1349
1350// ToString converts an interface value to a string. The interface should either be of
1351// a string type or []byte. Otherwise, an error is returned.
1352func ToString(value interface{}) (string, error) {
1353 switch t := value.(type) {
1354 case []byte:
1355 return string(value.([]byte)), nil
1356 case string:
1357 return value.(string), nil
1358 default:
1359 return "", fmt.Errorf("unexpected-type-%T", t)
1360 }
1361}