blob: ad2150ade73872edac4c1e2fbc13e13a6de4603f [file] [log] [blame]
Scott Baker2c1c4822019-10-16 11:02:41 -07001/*
2 * Copyright 2019-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package ponresourcemanager
18
19import (
npujar5bf737f2020-01-16 19:35:25 +053020 "context"
Scott Baker2c1c4822019-10-16 11:02:41 -070021 "encoding/base64"
22 "encoding/json"
23 "errors"
24 "fmt"
25 "strconv"
26
serkant.uluderyab38671c2019-11-01 09:35:38 -070027 bitmap "github.com/boljen/go-bitmap"
28 "github.com/opencord/voltha-lib-go/v3/pkg/db"
29 "github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore"
30 "github.com/opencord/voltha-lib-go/v3/pkg/log"
31 tp "github.com/opencord/voltha-lib-go/v3/pkg/techprofile"
Scott Baker2c1c4822019-10-16 11:02:41 -070032)
33
34const (
35 //Constants to identify resource pool
36 UNI_ID = "UNI_ID"
37 ONU_ID = "ONU_ID"
38 ALLOC_ID = "ALLOC_ID"
39 GEMPORT_ID = "GEMPORT_ID"
40 FLOW_ID = "FLOW_ID"
41
42 //Constants for passing command line arugments
43 OLT_MODEL_ARG = "--olt_model"
44 PATH_PREFIX = "service/voltha/resource_manager/{%s}"
45 /*The resource ranges for a given device model should be placed
46 at 'resource_manager/<technology>/resource_ranges/<olt_model_type>'
47 path on the KV store.
48 If Resource Range parameters are to be read from the external KV store,
49 they are expected to be stored in the following format.
50 Note: All parameters are MANDATORY for now.
51 constants used as keys to reference the resource range parameters from
52 and external KV store.
53 */
54 UNI_ID_START_IDX = "uni_id_start"
55 UNI_ID_END_IDX = "uni_id_end"
56 ONU_ID_START_IDX = "onu_id_start"
57 ONU_ID_END_IDX = "onu_id_end"
58 ONU_ID_SHARED_IDX = "onu_id_shared"
59 ALLOC_ID_START_IDX = "alloc_id_start"
60 ALLOC_ID_END_IDX = "alloc_id_end"
61 ALLOC_ID_SHARED_IDX = "alloc_id_shared"
62 GEMPORT_ID_START_IDX = "gemport_id_start"
63 GEMPORT_ID_END_IDX = "gemport_id_end"
64 GEMPORT_ID_SHARED_IDX = "gemport_id_shared"
65 FLOW_ID_START_IDX = "flow_id_start"
66 FLOW_ID_END_IDX = "flow_id_end"
67 FLOW_ID_SHARED_IDX = "flow_id_shared"
68 NUM_OF_PON_PORT = "pon_ports"
69
70 /*
71 The KV store backend is initialized with a path prefix and we need to
72 provide only the suffix.
73 */
74 PON_RESOURCE_RANGE_CONFIG_PATH = "resource_ranges/%s"
75
76 //resource path suffix
77 //Path on the KV store for storing alloc id ranges and resource pool for a given interface
78 //Format: <device_id>/alloc_id_pool/<pon_intf_id>
79 ALLOC_ID_POOL_PATH = "{%s}/alloc_id_pool/{%d}"
80 //Path on the KV store for storing gemport id ranges and resource pool for a given interface
81 //Format: <device_id>/gemport_id_pool/<pon_intf_id>
82 GEMPORT_ID_POOL_PATH = "{%s}/gemport_id_pool/{%d}"
83 //Path on the KV store for storing onu id ranges and resource pool for a given interface
84 //Format: <device_id>/onu_id_pool/<pon_intf_id>
85 ONU_ID_POOL_PATH = "{%s}/onu_id_pool/{%d}"
86 //Path on the KV store for storing flow id ranges and resource pool for a given interface
87 //Format: <device_id>/flow_id_pool/<pon_intf_id>
88 FLOW_ID_POOL_PATH = "{%s}/flow_id_pool/{%d}"
89
90 //Path on the KV store for storing list of alloc IDs for a given ONU
91 //Format: <device_id>/<(pon_intf_id, onu_id)>/alloc_ids
92 ALLOC_ID_RESOURCE_MAP_PATH = "{%s}/{%s}/alloc_ids"
93
94 //Path on the KV store for storing list of gemport IDs for a given ONU
95 //Format: <device_id>/<(pon_intf_id, onu_id)>/gemport_ids
96 GEMPORT_ID_RESOURCE_MAP_PATH = "{%s}/{%s}/gemport_ids"
97
98 //Path on the KV store for storing list of Flow IDs for a given ONU
99 //Format: <device_id>/<(pon_intf_id, onu_id)>/flow_ids
100 FLOW_ID_RESOURCE_MAP_PATH = "{%s}/{%s}/flow_ids"
101
102 //Flow Id info: Use to store more metadata associated with the flow_id
103 //Format: <device_id>/<(pon_intf_id, onu_id)>/flow_id_info/<flow_id>
104 FLOW_ID_INFO_PATH = "{%s}/{%s}/flow_id_info/{%d}"
105
Abhilash Laxmeshwarbbb0b2b2019-10-31 17:04:29 +0530106 //path on the kvstore to store onugem info map
107 //format: <device-id>/onu_gem_info/<intfid>
108 ONU_GEM_INFO_PATH = "{%s}/onu_gem_info/{%d}" // onu_gem/<(intfid)>
109
Scott Baker2c1c4822019-10-16 11:02:41 -0700110 //Constants for internal usage.
111 PON_INTF_ID = "pon_intf_id"
112 START_IDX = "start_idx"
113 END_IDX = "end_idx"
114 POOL = "pool"
115 NUM_OF_PON_INTF = 16
116
117 KVSTORE_RETRY_TIMEOUT = 5
118)
119
120//type ResourceTypeIndex string
121//type ResourceType string
122
123type PONResourceManager struct {
124 //Implements APIs to initialize/allocate/release alloc/gemport/onu IDs.
125 Technology string
126 DeviceType string
127 DeviceID string
128 Backend string // ETCD, or consul
129 Host string // host ip of the KV store
130 Port int // port number for the KV store
131 OLTModel string
sbarbari1e3e29c2019-11-05 10:06:50 -0500132 KVStore *db.Backend
Scott Baker2c1c4822019-10-16 11:02:41 -0700133 TechProfileMgr tp.TechProfileIf // create object of *tp.TechProfileMgr
134
135 // Below attribute, pon_resource_ranges, should be initialized
136 // by reading from KV store.
137 PonResourceRanges map[string]interface{}
138 SharedResourceMgrs map[string]*PONResourceManager
139 SharedIdxByType map[string]string
140 IntfIDs []uint32 // list of pon interface IDs
141 Globalorlocal string
142}
143
144func newKVClient(storeType string, address string, timeout int) (kvstore.Client, error) {
145 log.Infow("kv-store-type", log.Fields{"store": storeType})
146 switch storeType {
147 case "consul":
148 return kvstore.NewConsulClient(address, timeout)
149 case "etcd":
150 return kvstore.NewEtcdClient(address, timeout)
151 }
152 return nil, errors.New("unsupported-kv-store")
153}
154
sbarbari1e3e29c2019-11-05 10:06:50 -0500155func SetKVClient(Technology string, Backend string, Host string, Port int) *db.Backend {
Scott Baker2c1c4822019-10-16 11:02:41 -0700156 addr := Host + ":" + strconv.Itoa(Port)
157 // TODO : Make sure direct call to NewBackend is working fine with backend , currently there is some
158 // issue between kv store and backend , core is not calling NewBackend directly
159 kvClient, err := newKVClient(Backend, addr, KVSTORE_RETRY_TIMEOUT)
160 if err != nil {
161 log.Fatalw("Failed to init KV client\n", log.Fields{"err": err})
162 return nil
163 }
sbarbari1e3e29c2019-11-05 10:06:50 -0500164 kvbackend := &db.Backend{
Scott Baker2c1c4822019-10-16 11:02:41 -0700165 Client: kvClient,
166 StoreType: Backend,
167 Host: Host,
168 Port: Port,
169 Timeout: KVSTORE_RETRY_TIMEOUT,
170 PathPrefix: fmt.Sprintf(PATH_PREFIX, Technology)}
171
172 return kvbackend
173}
174
175// NewPONResourceManager creates a new PON resource manager.
176func NewPONResourceManager(Technology string, DeviceType string, DeviceID string, Backend string, Host string, Port int) (*PONResourceManager, error) {
177 var PONMgr PONResourceManager
178 PONMgr.Technology = Technology
179 PONMgr.DeviceType = DeviceType
180 PONMgr.DeviceID = DeviceID
181 PONMgr.Backend = Backend
182 PONMgr.Host = Host
183 PONMgr.Port = Port
184 PONMgr.KVStore = SetKVClient(Technology, Backend, Host, Port)
185 if PONMgr.KVStore == nil {
186 log.Error("KV Client initilization failed")
187 return nil, errors.New("Failed to init KV client")
188 }
189 // Initialize techprofile for this technology
190 if PONMgr.TechProfileMgr, _ = tp.NewTechProfile(&PONMgr, Backend, Host, Port); PONMgr.TechProfileMgr == nil {
191 log.Error("Techprofile initialization failed")
192 return nil, errors.New("Failed to init tech profile")
193 }
194 PONMgr.PonResourceRanges = make(map[string]interface{})
195 PONMgr.SharedResourceMgrs = make(map[string]*PONResourceManager)
196 PONMgr.SharedIdxByType = make(map[string]string)
197 PONMgr.SharedIdxByType[ONU_ID] = ONU_ID_SHARED_IDX
198 PONMgr.SharedIdxByType[ALLOC_ID] = ALLOC_ID_SHARED_IDX
199 PONMgr.SharedIdxByType[GEMPORT_ID] = GEMPORT_ID_SHARED_IDX
200 PONMgr.SharedIdxByType[FLOW_ID] = FLOW_ID_SHARED_IDX
201 PONMgr.IntfIDs = make([]uint32, NUM_OF_PON_INTF)
202 PONMgr.OLTModel = DeviceType
203 return &PONMgr, nil
204}
205
206/*
207 Initialize PON resource ranges with config fetched from kv store.
208 return boolean: True if PON resource ranges initialized else false
209 Try to initialize the PON Resource Ranges from KV store based on the
210 OLT model key, if available
211*/
212
npujar5bf737f2020-01-16 19:35:25 +0530213func (PONRMgr *PONResourceManager) InitResourceRangesFromKVStore(ctx context.Context) bool {
Scott Baker2c1c4822019-10-16 11:02:41 -0700214 //Initialize PON resource ranges with config fetched from kv store.
215 //:return boolean: True if PON resource ranges initialized else false
216 // Try to initialize the PON Resource Ranges from KV store based on the
217 // OLT model key, if available
218 if PONRMgr.OLTModel == "" {
219 log.Error("Failed to get OLT model")
220 return false
221 }
222 Path := fmt.Sprintf(PON_RESOURCE_RANGE_CONFIG_PATH, PONRMgr.OLTModel)
223 //get resource from kv store
npujar5bf737f2020-01-16 19:35:25 +0530224 Result, err := PONRMgr.KVStore.Get(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700225 if err != nil {
226 log.Debugf("Error in fetching resource %s from KV strore", Path)
227 return false
228 }
229 if Result == nil {
230 log.Debug("There may be no resources in the KV store in case of fresh bootup, return true")
231 return false
232 }
233 //update internal ranges from kv ranges. If there are missing
234 // values in the KV profile, continue to use the defaults
235 Value, err := ToByte(Result.Value)
236 if err != nil {
237 log.Error("Failed to convert kvpair to byte string")
238 return false
239 }
240 if err := json.Unmarshal(Value, &PONRMgr.PonResourceRanges); err != nil {
241 log.Error("Failed to Unmarshal json byte")
242 return false
243 }
244 log.Debug("Init resource ranges from kvstore success")
245 return true
246}
247
248func (PONRMgr *PONResourceManager) UpdateRanges(StartIDx string, StartID uint32, EndIDx string, EndID uint32,
249 SharedIDx string, SharedPoolID uint32, RMgr *PONResourceManager) {
250 /*
251 Update the ranges for all reosurce type in the intermnal maps
252 param: resource type start index
253 param: start ID
254 param: resource type end index
255 param: end ID
256 param: resource type shared index
257 param: shared pool id
258 param: global resource manager
259 */
260 log.Debugf("update ranges for %s, %d", StartIDx, StartID)
261
262 if StartID != 0 {
263 if (PONRMgr.PonResourceRanges[StartIDx] == nil) || (PONRMgr.PonResourceRanges[StartIDx].(uint32) < StartID) {
264 PONRMgr.PonResourceRanges[StartIDx] = StartID
265 }
266 }
267 if EndID != 0 {
268 if (PONRMgr.PonResourceRanges[EndIDx] == nil) || (PONRMgr.PonResourceRanges[EndIDx].(uint32) > EndID) {
269 PONRMgr.PonResourceRanges[EndIDx] = EndID
270 }
271 }
272 //if SharedPoolID != 0 {
273 PONRMgr.PonResourceRanges[SharedIDx] = SharedPoolID
274 //}
275 if RMgr != nil {
276 PONRMgr.SharedResourceMgrs[SharedIDx] = RMgr
277 }
278}
279
280func (PONRMgr *PONResourceManager) InitDefaultPONResourceRanges(ONUIDStart uint32,
281 ONUIDEnd uint32,
282 ONUIDSharedPoolID uint32,
283 AllocIDStart uint32,
284 AllocIDEnd uint32,
285 AllocIDSharedPoolID uint32,
286 GEMPortIDStart uint32,
287 GEMPortIDEnd uint32,
288 GEMPortIDSharedPoolID uint32,
289 FlowIDStart uint32,
290 FlowIDEnd uint32,
291 FlowIDSharedPoolID uint32,
292 UNIIDStart uint32,
293 UNIIDEnd uint32,
294 NoOfPONPorts uint32,
295 IntfIDs []uint32) bool {
296
297 /*Initialize default PON resource ranges
298
299 :param onu_id_start_idx: onu id start index
300 :param onu_id_end_idx: onu id end index
301 :param onu_id_shared_pool_id: pool idx for id shared by all intfs or None for no sharing
302 :param alloc_id_start_idx: alloc id start index
303 :param alloc_id_end_idx: alloc id end index
304 :param alloc_id_shared_pool_id: pool idx for alloc id shared by all intfs or None for no sharing
305 :param gemport_id_start_idx: gemport id start index
306 :param gemport_id_end_idx: gemport id end index
307 :param gemport_id_shared_pool_id: pool idx for gemport id shared by all intfs or None for no sharing
308 :param flow_id_start_idx: flow id start index
309 :param flow_id_end_idx: flow id end index
310 :param flow_id_shared_pool_id: pool idx for flow id shared by all intfs or None for no sharing
311 :param num_of_pon_ports: number of PON ports
312 :param intf_ids: interfaces serviced by this manager
313 */
314 PONRMgr.UpdateRanges(ONU_ID_START_IDX, ONUIDStart, ONU_ID_END_IDX, ONUIDEnd, ONU_ID_SHARED_IDX, ONUIDSharedPoolID, nil)
315 PONRMgr.UpdateRanges(ALLOC_ID_START_IDX, AllocIDStart, ALLOC_ID_END_IDX, AllocIDEnd, ALLOC_ID_SHARED_IDX, AllocIDSharedPoolID, nil)
316 PONRMgr.UpdateRanges(GEMPORT_ID_START_IDX, GEMPortIDStart, GEMPORT_ID_END_IDX, GEMPortIDEnd, GEMPORT_ID_SHARED_IDX, GEMPortIDSharedPoolID, nil)
317 PONRMgr.UpdateRanges(FLOW_ID_START_IDX, FlowIDStart, FLOW_ID_END_IDX, FlowIDEnd, FLOW_ID_SHARED_IDX, FlowIDSharedPoolID, nil)
318 PONRMgr.UpdateRanges(UNI_ID_START_IDX, UNIIDStart, UNI_ID_END_IDX, UNIIDEnd, "", 0, nil)
319 log.Debug("Initialize default range values")
320 var i uint32
321 if IntfIDs == nil {
322 for i = 0; i < NoOfPONPorts; i++ {
323 PONRMgr.IntfIDs = append(PONRMgr.IntfIDs, i)
324 }
325 } else {
326 PONRMgr.IntfIDs = IntfIDs
327 }
328 return true
329}
330
npujar5bf737f2020-01-16 19:35:25 +0530331func (PONRMgr *PONResourceManager) InitDeviceResourcePool(ctx context.Context) error {
Scott Baker2c1c4822019-10-16 11:02:41 -0700332
333 //Initialize resource pool for all PON ports.
334
335 log.Debug("Init resource ranges")
336
337 var err error
338 for _, Intf := range PONRMgr.IntfIDs {
339 SharedPoolID := PONRMgr.PonResourceRanges[ONU_ID_SHARED_IDX].(uint32)
340 if SharedPoolID != 0 {
341 Intf = SharedPoolID
342 }
npujar5bf737f2020-01-16 19:35:25 +0530343 if err = PONRMgr.InitResourceIDPool(ctx, Intf, ONU_ID,
Scott Baker2c1c4822019-10-16 11:02:41 -0700344 PONRMgr.PonResourceRanges[ONU_ID_START_IDX].(uint32),
345 PONRMgr.PonResourceRanges[ONU_ID_END_IDX].(uint32)); err != nil {
346 log.Error("Failed to init ONU ID resource pool")
347 return err
348 }
349 if SharedPoolID != 0 {
350 break
351 }
352 }
353
354 for _, Intf := range PONRMgr.IntfIDs {
355 SharedPoolID := PONRMgr.PonResourceRanges[ALLOC_ID_SHARED_IDX].(uint32)
356 if SharedPoolID != 0 {
357 Intf = SharedPoolID
358 }
npujar5bf737f2020-01-16 19:35:25 +0530359 if err = PONRMgr.InitResourceIDPool(ctx, Intf, ALLOC_ID,
Scott Baker2c1c4822019-10-16 11:02:41 -0700360 PONRMgr.PonResourceRanges[ALLOC_ID_START_IDX].(uint32),
361 PONRMgr.PonResourceRanges[ALLOC_ID_END_IDX].(uint32)); err != nil {
362 log.Error("Failed to init ALLOC ID resource pool ")
363 return err
364 }
365 if SharedPoolID != 0 {
366 break
367 }
368 }
369 for _, Intf := range PONRMgr.IntfIDs {
370 SharedPoolID := PONRMgr.PonResourceRanges[GEMPORT_ID_SHARED_IDX].(uint32)
371 if SharedPoolID != 0 {
372 Intf = SharedPoolID
373 }
npujar5bf737f2020-01-16 19:35:25 +0530374 if err = PONRMgr.InitResourceIDPool(ctx, Intf, GEMPORT_ID,
Scott Baker2c1c4822019-10-16 11:02:41 -0700375 PONRMgr.PonResourceRanges[GEMPORT_ID_START_IDX].(uint32),
376 PONRMgr.PonResourceRanges[GEMPORT_ID_END_IDX].(uint32)); err != nil {
377 log.Error("Failed to init GEMPORT ID resource pool")
378 return err
379 }
380 if SharedPoolID != 0 {
381 break
382 }
383 }
384
385 for _, Intf := range PONRMgr.IntfIDs {
386 SharedPoolID := PONRMgr.PonResourceRanges[FLOW_ID_SHARED_IDX].(uint32)
387 if SharedPoolID != 0 {
388 Intf = SharedPoolID
389 }
npujar5bf737f2020-01-16 19:35:25 +0530390 if err = PONRMgr.InitResourceIDPool(ctx, Intf, FLOW_ID,
Scott Baker2c1c4822019-10-16 11:02:41 -0700391 PONRMgr.PonResourceRanges[FLOW_ID_START_IDX].(uint32),
392 PONRMgr.PonResourceRanges[FLOW_ID_END_IDX].(uint32)); err != nil {
393 log.Error("Failed to init FLOW ID resource pool")
394 return err
395 }
396 if SharedPoolID != 0 {
397 break
398 }
399 }
400 return err
401}
402
npujar5bf737f2020-01-16 19:35:25 +0530403func (PONRMgr *PONResourceManager) ClearDeviceResourcePool(ctx context.Context) error {
Scott Baker2c1c4822019-10-16 11:02:41 -0700404
405 //Clear resource pool for all PON ports.
406
407 log.Debug("Clear resource ranges")
408
409 for _, Intf := range PONRMgr.IntfIDs {
410 SharedPoolID := PONRMgr.PonResourceRanges[ONU_ID_SHARED_IDX].(uint32)
411 if SharedPoolID != 0 {
412 Intf = SharedPoolID
413 }
npujar5bf737f2020-01-16 19:35:25 +0530414 if status := PONRMgr.ClearResourceIDPool(ctx, Intf, ONU_ID); status != true {
Scott Baker2c1c4822019-10-16 11:02:41 -0700415 log.Error("Failed to clear ONU ID resource pool")
416 return errors.New("Failed to clear ONU ID resource pool")
417 }
418 if SharedPoolID != 0 {
419 break
420 }
421 }
422
423 for _, Intf := range PONRMgr.IntfIDs {
424 SharedPoolID := PONRMgr.PonResourceRanges[ALLOC_ID_SHARED_IDX].(uint32)
425 if SharedPoolID != 0 {
426 Intf = SharedPoolID
427 }
npujar5bf737f2020-01-16 19:35:25 +0530428 if status := PONRMgr.ClearResourceIDPool(ctx, Intf, ALLOC_ID); status != true {
Scott Baker2c1c4822019-10-16 11:02:41 -0700429 log.Error("Failed to clear ALLOC ID resource pool ")
430 return errors.New("Failed to clear ALLOC ID resource pool")
431 }
432 if SharedPoolID != 0 {
433 break
434 }
435 }
436 for _, Intf := range PONRMgr.IntfIDs {
437 SharedPoolID := PONRMgr.PonResourceRanges[GEMPORT_ID_SHARED_IDX].(uint32)
438 if SharedPoolID != 0 {
439 Intf = SharedPoolID
440 }
npujar5bf737f2020-01-16 19:35:25 +0530441 if status := PONRMgr.ClearResourceIDPool(ctx, Intf, GEMPORT_ID); status != true {
Scott Baker2c1c4822019-10-16 11:02:41 -0700442 log.Error("Failed to clear GEMPORT ID resource pool")
443 return errors.New("Failed to clear GEMPORT ID resource pool")
444 }
445 if SharedPoolID != 0 {
446 break
447 }
448 }
449
450 for _, Intf := range PONRMgr.IntfIDs {
451 SharedPoolID := PONRMgr.PonResourceRanges[FLOW_ID_SHARED_IDX].(uint32)
452 if SharedPoolID != 0 {
453 Intf = SharedPoolID
454 }
npujar5bf737f2020-01-16 19:35:25 +0530455 if status := PONRMgr.ClearResourceIDPool(ctx, Intf, FLOW_ID); status != true {
Scott Baker2c1c4822019-10-16 11:02:41 -0700456 log.Error("Failed to clear FLOW ID resource pool")
457 return errors.New("Failed to clear FLOW ID resource pool")
458 }
459 if SharedPoolID != 0 {
460 break
461 }
462 }
463 return nil
464}
465
npujar5bf737f2020-01-16 19:35:25 +0530466func (PONRMgr *PONResourceManager) InitResourceIDPool(ctx context.Context, Intf uint32, ResourceType string, StartID uint32, EndID uint32) error {
Scott Baker2c1c4822019-10-16 11:02:41 -0700467
468 /*Initialize Resource ID pool for a given Resource Type on a given PON Port
469
470 :param pon_intf_id: OLT PON interface id
471 :param resource_type: String to identify type of resource
472 :param start_idx: start index for onu id pool
473 :param end_idx: end index for onu id pool
474 :return boolean: True if resource id pool initialized else false
475 */
476
477 // delegate to the master instance if sharing enabled across instances
478 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
479 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
npujar5bf737f2020-01-16 19:35:25 +0530480 return SharedResourceMgr.InitResourceIDPool(ctx, Intf, ResourceType, StartID, EndID)
Scott Baker2c1c4822019-10-16 11:02:41 -0700481 }
482
483 Path := PONRMgr.GetPath(Intf, ResourceType)
484 if Path == "" {
485 log.Errorf("Failed to get path for resource type %s", ResourceType)
486 return errors.New(fmt.Sprintf("Failed to get path for resource type %s", ResourceType))
487 }
488
489 //In case of adapter reboot and reconciliation resource in kv store
490 //checked for its presence if not kv store update happens
npujar5bf737f2020-01-16 19:35:25 +0530491 Res, err := PONRMgr.GetResource(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700492 if (err == nil) && (Res != nil) {
493 log.Debugf("Resource %s already present in store ", Path)
494 return nil
495 } else {
496 FormatResult, err := PONRMgr.FormatResource(Intf, StartID, EndID)
497 if err != nil {
498 log.Errorf("Failed to format resource")
499 return err
500 }
501 // Add resource as json in kv store.
npujar5bf737f2020-01-16 19:35:25 +0530502 err = PONRMgr.KVStore.Put(ctx, Path, FormatResult)
Scott Baker2c1c4822019-10-16 11:02:41 -0700503 if err == nil {
504 log.Debug("Successfuly posted to kv store")
505 return err
506 }
507 }
508
509 log.Debug("Error initializing pool")
510
511 return err
512}
513
514func (PONRMgr *PONResourceManager) FormatResource(IntfID uint32, StartIDx uint32, EndIDx uint32) ([]byte, error) {
515 /*
516 Format resource as json.
517 :param pon_intf_id: OLT PON interface id
518 :param start_idx: start index for id pool
519 :param end_idx: end index for id pool
520 :return dictionary: resource formatted as map
521 */
522 // Format resource as json to be stored in backend store
523 Resource := make(map[string]interface{})
524 Resource[PON_INTF_ID] = IntfID
525 Resource[START_IDX] = StartIDx
526 Resource[END_IDX] = EndIDx
527 /*
528 Resource pool stored in backend store as binary string.
529 Tracking the resource allocation will be done by setting the bits \
530 in the byte array. The index set will be the resource number allocated.
531 */
532 var TSData *bitmap.Threadsafe
533 if TSData = bitmap.NewTS(int(EndIDx)); TSData == nil {
534 log.Error("Failed to create a bitmap")
535 return nil, errors.New("Failed to create bitmap")
536 }
537 Resource[POOL] = TSData.Data(false) //we pass false so as the TSData lib api does not do a copy of the data and return
538
539 Value, err := json.Marshal(Resource)
540 if err != nil {
541 log.Errorf("Failed to marshall resource")
542 return nil, err
543 }
544 return Value, err
545}
npujar5bf737f2020-01-16 19:35:25 +0530546func (PONRMgr *PONResourceManager) GetResource(ctx context.Context, Path string) (map[string]interface{}, error) {
Scott Baker2c1c4822019-10-16 11:02:41 -0700547 /*
548 Get resource from kv store.
549
550 :param path: path to get resource
551 :return: resource if resource present in kv store else None
552 */
553 //get resource from kv store
554
555 var Value []byte
556 Result := make(map[string]interface{})
557 var Str string
558
npujar5bf737f2020-01-16 19:35:25 +0530559 Resource, err := PONRMgr.KVStore.Get(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700560 if (err != nil) || (Resource == nil) {
561 log.Debugf("Resource unavailable at %s", Path)
562 return nil, err
563 }
564
565 Value, err = ToByte(Resource.Value)
566
567 // decode resource fetched from backend store to dictionary
568 err = json.Unmarshal(Value, &Result)
569 if err != nil {
570 log.Error("Failed to decode resource")
571 return Result, err
572 }
573 /*
574 resource pool in backend store stored as binary string whereas to
575 access the pool to generate/release IDs it need to be converted
576 as BitArray
577 */
578 Str, err = ToString(Result[POOL])
579 if err != nil {
580 log.Error("Failed to conver to kv pair to string")
581 return Result, err
582 }
583 Decode64, _ := base64.StdEncoding.DecodeString(Str)
584 Result[POOL], err = ToByte(Decode64)
585 if err != nil {
586 log.Error("Failed to convert resource pool to byte")
587 return Result, err
588 }
589
590 return Result, err
591}
592
593func (PONRMgr *PONResourceManager) GetPath(IntfID uint32, ResourceType string) string {
594 /*
595 Get path for given resource type.
596 :param pon_intf_id: OLT PON interface id
597 :param resource_type: String to identify type of resource
598 :return: path for given resource type
599 */
600
601 /*
602 Get the shared pool for the given resource type.
603 all the resource ranges and the shared resource maps are initialized during the init.
604 */
605 SharedPoolID := PONRMgr.PonResourceRanges[PONRMgr.SharedIdxByType[ResourceType]].(uint32)
606 if SharedPoolID != 0 {
607 IntfID = SharedPoolID
608 }
609 var Path string
610 if ResourceType == ONU_ID {
611 Path = fmt.Sprintf(ONU_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
612 } else if ResourceType == ALLOC_ID {
613 Path = fmt.Sprintf(ALLOC_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
614 } else if ResourceType == GEMPORT_ID {
615 Path = fmt.Sprintf(GEMPORT_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
616 } else if ResourceType == FLOW_ID {
617 Path = fmt.Sprintf(FLOW_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
618 } else {
619 log.Error("Invalid resource pool identifier")
620 }
621 return Path
622}
623
npujar5bf737f2020-01-16 19:35:25 +0530624func (PONRMgr *PONResourceManager) GetResourceID(ctx context.Context, IntfID uint32, ResourceType string, NumIDs uint32) ([]uint32, error) {
Scott Baker2c1c4822019-10-16 11:02:41 -0700625 /*
626 Create alloc/gemport/onu/flow id for given OLT PON interface.
627 :param pon_intf_id: OLT PON interface id
628 :param resource_type: String to identify type of resource
629 :param num_of_id: required number of ids
630 :return list/uint32/None: list, uint32 or None if resource type is
631 alloc_id/gemport_id, onu_id or invalid type respectively
632 */
633 if NumIDs < 1 {
634 log.Error("Invalid number of resources requested")
635 return nil, errors.New(fmt.Sprintf("Invalid number of resources requested %d", NumIDs))
636 }
637 // delegate to the master instance if sharing enabled across instances
638
639 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
640 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
npujar5bf737f2020-01-16 19:35:25 +0530641 return SharedResourceMgr.GetResourceID(ctx, IntfID, ResourceType, NumIDs)
Scott Baker2c1c4822019-10-16 11:02:41 -0700642 }
643 log.Debugf("Fetching resource from %s rsrc mgr for resource %s", PONRMgr.Globalorlocal, ResourceType)
644
645 Path := PONRMgr.GetPath(IntfID, ResourceType)
646 if Path == "" {
647 log.Errorf("Failed to get path for resource type %s", ResourceType)
648 return nil, errors.New(fmt.Sprintf("Failed to get path for resource type %s", ResourceType))
649 }
650 log.Debugf("Get resource for type %s on path %s", ResourceType, Path)
651 var Result []uint32
652 var NextID uint32
npujar5bf737f2020-01-16 19:35:25 +0530653 Resource, err := PONRMgr.GetResource(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700654 if (err == nil) && (ResourceType == ONU_ID) || (ResourceType == FLOW_ID) {
655 if NextID, err = PONRMgr.GenerateNextID(Resource); err != nil {
656 log.Error("Failed to Generate ID")
657 return Result, err
658 }
659 Result = append(Result, NextID)
660 } else if (err == nil) && ((ResourceType == GEMPORT_ID) || (ResourceType == ALLOC_ID)) {
661 if NumIDs == 1 {
662 if NextID, err = PONRMgr.GenerateNextID(Resource); err != nil {
663 log.Error("Failed to Generate ID")
664 return Result, err
665 }
666 Result = append(Result, NextID)
667 } else {
668 for NumIDs > 0 {
669 if NextID, err = PONRMgr.GenerateNextID(Resource); err != nil {
670 log.Error("Failed to Generate ID")
671 return Result, err
672 }
673 Result = append(Result, NextID)
674 NumIDs--
675 }
676 }
677 } else {
678 log.Error("get resource failed")
679 return Result, err
680 }
681
682 //Update resource in kv store
npujar5bf737f2020-01-16 19:35:25 +0530683 if PONRMgr.UpdateResource(ctx, Path, Resource) != nil {
Scott Baker2c1c4822019-10-16 11:02:41 -0700684 log.Errorf("Failed to update resource %s", Path)
685 return nil, errors.New(fmt.Sprintf("Failed to update resource %s", Path))
686 }
687 return Result, nil
688}
689
690func checkValidResourceType(ResourceType string) bool {
691 KnownResourceTypes := []string{ONU_ID, ALLOC_ID, GEMPORT_ID, FLOW_ID}
692
693 for _, v := range KnownResourceTypes {
694 if v == ResourceType {
695 return true
696 }
697 }
698 return false
699}
700
npujar5bf737f2020-01-16 19:35:25 +0530701func (PONRMgr *PONResourceManager) FreeResourceID(ctx context.Context, IntfID uint32, ResourceType string, ReleaseContent []uint32) bool {
Scott Baker2c1c4822019-10-16 11:02:41 -0700702 /*
703 Release alloc/gemport/onu/flow id for given OLT PON interface.
704 :param pon_intf_id: OLT PON interface id
705 :param resource_type: String to identify type of resource
706 :param release_content: required number of ids
707 :return boolean: True if all IDs in given release_content release else False
708 */
709 if checkValidResourceType(ResourceType) == false {
710 log.Error("Invalid resource type")
711 return false
712 }
713 if ReleaseContent == nil {
714 log.Debug("Nothing to release")
715 return true
716 }
717 // delegate to the master instance if sharing enabled across instances
718 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
719 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
npujar5bf737f2020-01-16 19:35:25 +0530720 return SharedResourceMgr.FreeResourceID(ctx, IntfID, ResourceType, ReleaseContent)
Scott Baker2c1c4822019-10-16 11:02:41 -0700721 }
722 Path := PONRMgr.GetPath(IntfID, ResourceType)
723 if Path == "" {
724 log.Error("Failed to get path")
725 return false
726 }
npujar5bf737f2020-01-16 19:35:25 +0530727 Resource, err := PONRMgr.GetResource(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700728 if err != nil {
729 log.Error("Failed to get resource")
730 return false
731 }
732 for _, Val := range ReleaseContent {
733 PONRMgr.ReleaseID(Resource, Val)
734 }
npujar5bf737f2020-01-16 19:35:25 +0530735 if PONRMgr.UpdateResource(ctx, Path, Resource) != nil {
Scott Baker2c1c4822019-10-16 11:02:41 -0700736 log.Errorf("Free resource for %s failed", Path)
737 return false
738 }
739 return true
740}
741
npujar5bf737f2020-01-16 19:35:25 +0530742func (PONRMgr *PONResourceManager) UpdateResource(ctx context.Context, Path string, Resource map[string]interface{}) error {
Scott Baker2c1c4822019-10-16 11:02:41 -0700743 /*
744 Update resource in resource kv store.
745 :param path: path to update resource
746 :param resource: resource need to be updated
747 :return boolean: True if resource updated in kv store else False
748 */
749 // TODO resource[POOL] = resource[POOL].bin
750 Value, err := json.Marshal(Resource)
751 if err != nil {
752 log.Error("failed to Marshal")
753 return err
754 }
npujar5bf737f2020-01-16 19:35:25 +0530755 err = PONRMgr.KVStore.Put(ctx, Path, Value)
Scott Baker2c1c4822019-10-16 11:02:41 -0700756 if err != nil {
757 log.Error("failed to put data to kv store %s", Path)
758 return err
759 }
760 return nil
761}
762
npujar5bf737f2020-01-16 19:35:25 +0530763func (PONRMgr *PONResourceManager) ClearResourceIDPool(ctx context.Context, contIntfID uint32, ResourceType string) bool {
Scott Baker2c1c4822019-10-16 11:02:41 -0700764 /*
765 Clear Resource Pool for a given Resource Type on a given PON Port.
766 :return boolean: True if removed else False
767 */
768
769 // delegate to the master instance if sharing enabled across instances
770 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
771 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
npujar5bf737f2020-01-16 19:35:25 +0530772 return SharedResourceMgr.ClearResourceIDPool(ctx, contIntfID, ResourceType)
Scott Baker2c1c4822019-10-16 11:02:41 -0700773 }
npujar5bf737f2020-01-16 19:35:25 +0530774 Path := PONRMgr.GetPath(contIntfID, ResourceType)
Scott Baker2c1c4822019-10-16 11:02:41 -0700775 if Path == "" {
776 log.Error("Failed to get path")
777 return false
778 }
779
npujar5bf737f2020-01-16 19:35:25 +0530780 if err := PONRMgr.KVStore.Delete(ctx, Path); err != nil {
Scott Baker2c1c4822019-10-16 11:02:41 -0700781 log.Errorf("Failed to delete resource %s", Path)
782 return false
783 }
784 log.Debugf("Cleared resource %s", Path)
785 return true
786}
787
npujar5bf737f2020-01-16 19:35:25 +0530788func (PONRMgr PONResourceManager) InitResourceMap(ctx context.Context, PONIntfONUID string) {
Scott Baker2c1c4822019-10-16 11:02:41 -0700789 /*
790 Initialize resource map
791 :param pon_intf_onu_id: reference of PON interface id and onu id
792 */
793 // initialize pon_intf_onu_id tuple to alloc_ids map
794 AllocIDPath := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
795 var AllocIDs []byte
npujar5bf737f2020-01-16 19:35:25 +0530796 Result := PONRMgr.KVStore.Put(ctx, AllocIDPath, AllocIDs)
Scott Baker2c1c4822019-10-16 11:02:41 -0700797 if Result != nil {
798 log.Error("Failed to update the KV store")
799 return
800 }
801 // initialize pon_intf_onu_id tuple to gemport_ids map
802 GEMPortIDPath := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
803 var GEMPortIDs []byte
npujar5bf737f2020-01-16 19:35:25 +0530804 Result = PONRMgr.KVStore.Put(ctx, GEMPortIDPath, GEMPortIDs)
Scott Baker2c1c4822019-10-16 11:02:41 -0700805 if Result != nil {
806 log.Error("Failed to update the KV store")
807 return
808 }
809}
810
npujar5bf737f2020-01-16 19:35:25 +0530811func (PONRMgr PONResourceManager) RemoveResourceMap(ctx context.Context, PONIntfONUID string) bool {
Scott Baker2c1c4822019-10-16 11:02:41 -0700812 /*
813 Remove resource map
814 :param pon_intf_onu_id: reference of PON interface id and onu id
815 */
816 // remove pon_intf_onu_id tuple to alloc_ids map
817 var err error
818 AllocIDPath := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
npujar5bf737f2020-01-16 19:35:25 +0530819 if err = PONRMgr.KVStore.Delete(ctx, AllocIDPath); err != nil {
Scott Baker2c1c4822019-10-16 11:02:41 -0700820 log.Errorf("Failed to remove resource %s", AllocIDPath)
821 return false
822 }
823 // remove pon_intf_onu_id tuple to gemport_ids map
824 GEMPortIDPath := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
npujar5bf737f2020-01-16 19:35:25 +0530825 err = PONRMgr.KVStore.Delete(ctx, GEMPortIDPath)
Scott Baker2c1c4822019-10-16 11:02:41 -0700826 if err != nil {
827 log.Errorf("Failed to remove resource %s", GEMPortIDPath)
828 return false
829 }
830
831 FlowIDPath := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
npujar5bf737f2020-01-16 19:35:25 +0530832 if FlowIDs, err := PONRMgr.KVStore.List(ctx, FlowIDPath); err != nil {
Scott Baker2c1c4822019-10-16 11:02:41 -0700833 for _, Flow := range FlowIDs {
834 FlowIDInfoPath := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, PONIntfONUID, Flow.Value)
npujar5bf737f2020-01-16 19:35:25 +0530835 if err = PONRMgr.KVStore.Delete(ctx, FlowIDInfoPath); err != nil {
Scott Baker2c1c4822019-10-16 11:02:41 -0700836 log.Errorf("Failed to remove resource %s", FlowIDInfoPath)
837 return false
838 }
839 }
840 }
841
npujar5bf737f2020-01-16 19:35:25 +0530842 if err = PONRMgr.KVStore.Delete(ctx, FlowIDPath); err != nil {
Scott Baker2c1c4822019-10-16 11:02:41 -0700843 log.Errorf("Failed to remove resource %s", FlowIDPath)
844 return false
845 }
846
847 return true
848}
849
npujar5bf737f2020-01-16 19:35:25 +0530850func (PONRMgr *PONResourceManager) GetCurrentAllocIDForOnu(ctx context.Context, IntfONUID string) []uint32 {
Scott Baker2c1c4822019-10-16 11:02:41 -0700851 /*
852 Get currently configured alloc ids for given pon_intf_onu_id
853 :param pon_intf_onu_id: reference of PON interface id and onu id
854 :return list: List of alloc_ids if available, else None
855 */
856 Path := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
857
858 var Data []uint32
npujar5bf737f2020-01-16 19:35:25 +0530859 Value, err := PONRMgr.KVStore.Get(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700860 if err == nil {
861 if Value != nil {
862 Val, err := ToByte(Value.Value)
863 if err != nil {
864 log.Errorw("Failed to convert into byte array", log.Fields{"error": err})
865 return Data
866 }
867 if err = json.Unmarshal(Val, &Data); err != nil {
868 log.Error("Failed to unmarshal", log.Fields{"error": err})
869 return Data
870 }
871 }
872 }
873 return Data
874}
875
npujar5bf737f2020-01-16 19:35:25 +0530876func (PONRMgr *PONResourceManager) GetCurrentGEMPortIDsForOnu(ctx context.Context, IntfONUID string) []uint32 {
Scott Baker2c1c4822019-10-16 11:02:41 -0700877 /*
878 Get currently configured gemport ids for given pon_intf_onu_id
879 :param pon_intf_onu_id: reference of PON interface id and onu id
880 :return list: List of gemport IDs if available, else None
881 */
882
883 Path := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
884 log.Debugf("Getting current gemports for %s", Path)
885 var Data []uint32
npujar5bf737f2020-01-16 19:35:25 +0530886 Value, err := PONRMgr.KVStore.Get(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700887 if err == nil {
888 if Value != nil {
889 Val, _ := ToByte(Value.Value)
890 if err = json.Unmarshal(Val, &Data); err != nil {
891 log.Errorw("Failed to unmarshal", log.Fields{"error": err})
892 return Data
893 }
894 }
895 } else {
896 log.Errorf("Failed to get data from kvstore for %s", Path)
897 }
898 return Data
899}
900
npujar5bf737f2020-01-16 19:35:25 +0530901func (PONRMgr *PONResourceManager) GetCurrentFlowIDsForOnu(ctx context.Context, IntfONUID string) []uint32 {
Scott Baker2c1c4822019-10-16 11:02:41 -0700902 /*
903 Get currently configured flow ids for given pon_intf_onu_id
904 :param pon_intf_onu_id: reference of PON interface id and onu id
905 :return list: List of Flow IDs if available, else None
906 */
907
908 Path := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
909
910 var Data []uint32
npujar5bf737f2020-01-16 19:35:25 +0530911 Value, err := PONRMgr.KVStore.Get(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700912 if err == nil {
913 if Value != nil {
914 Val, _ := ToByte(Value.Value)
915 if err = json.Unmarshal(Val, &Data); err != nil {
916 log.Error("Failed to unmarshal")
917 return Data
918 }
919 }
920 }
921 return Data
922}
923
npujar5bf737f2020-01-16 19:35:25 +0530924func (PONRMgr *PONResourceManager) GetFlowIDInfo(ctx context.Context, IntfONUID string, FlowID uint32, Data interface{}) error {
Scott Baker2c1c4822019-10-16 11:02:41 -0700925 /*
926 Get flow details configured for the ONU.
927 :param pon_intf_onu_id: reference of PON interface id and onu id
928 :param flow_id: Flow Id reference
929 :param Data: Result
930 :return error: nil if no error in getting from KV store
931 */
932
933 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
934
npujar5bf737f2020-01-16 19:35:25 +0530935 Value, err := PONRMgr.KVStore.Get(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700936 if err == nil {
937 if Value != nil {
938 Val, err := ToByte(Value.Value)
939 if err != nil {
940 log.Errorw("Failed to convert flowinfo into byte array", log.Fields{"error": err})
941 return err
942 }
943 if err = json.Unmarshal(Val, Data); err != nil {
944 log.Errorw("Failed to unmarshal", log.Fields{"error": err})
945 return err
946 }
947 }
948 }
949 return err
950}
951
npujar5bf737f2020-01-16 19:35:25 +0530952func (PONRMgr *PONResourceManager) RemoveFlowIDInfo(ctx context.Context, IntfONUID string, FlowID uint32) bool {
Scott Baker2c1c4822019-10-16 11:02:41 -0700953 /*
954 Get flow_id details configured for the ONU.
955 :param pon_intf_onu_id: reference of PON interface id and onu id
956 :param flow_id: Flow Id reference
957 */
958 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
959
npujar5bf737f2020-01-16 19:35:25 +0530960 if err := PONRMgr.KVStore.Delete(ctx, Path); err != nil {
Scott Baker2c1c4822019-10-16 11:02:41 -0700961 log.Errorf("Falied to remove resource %s", Path)
962 return false
963 }
964 return true
965}
966
npujar5bf737f2020-01-16 19:35:25 +0530967func (PONRMgr *PONResourceManager) UpdateAllocIdsForOnu(ctx context.Context, IntfONUID string, AllocIDs []uint32) error {
Scott Baker2c1c4822019-10-16 11:02:41 -0700968 /*
969 Update currently configured alloc ids for given pon_intf_onu_id
970 :param pon_intf_onu_id: reference of PON interface id and onu id
971 :param alloc_ids: list of alloc ids
972 */
973 var Value []byte
974 var err error
975 Path := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
976 Value, err = json.Marshal(AllocIDs)
977 if err != nil {
978 log.Error("failed to Marshal")
979 return err
980 }
981
npujar5bf737f2020-01-16 19:35:25 +0530982 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Scott Baker2c1c4822019-10-16 11:02:41 -0700983 log.Errorf("Failed to update resource %s", Path)
984 return err
985 }
986 return err
987}
988
npujar5bf737f2020-01-16 19:35:25 +0530989func (PONRMgr *PONResourceManager) UpdateGEMPortIDsForOnu(ctx context.Context, IntfONUID string, GEMPortIDs []uint32) error {
Scott Baker2c1c4822019-10-16 11:02:41 -0700990 /*
991 Update currently configured gemport ids for given pon_intf_onu_id
992 :param pon_intf_onu_id: reference of PON interface id and onu id
993 :param gemport_ids: list of gem port ids
994 */
995
996 var Value []byte
997 var err error
998 Path := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
999 log.Debugf("Updating gemport ids for %s", Path)
1000 Value, err = json.Marshal(GEMPortIDs)
1001 if err != nil {
1002 log.Error("failed to Marshal")
1003 return err
1004 }
1005
npujar5bf737f2020-01-16 19:35:25 +05301006 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Scott Baker2c1c4822019-10-16 11:02:41 -07001007 log.Errorf("Failed to update resource %s", Path)
1008 return err
1009 }
1010 return err
1011}
1012
1013func checkForFlowIDInList(FlowIDList []uint32, FlowID uint32) (bool, uint32) {
1014 /*
1015 Check for a flow id in a given list of flow IDs.
1016 :param FLowIDList: List of Flow IDs
1017 :param FlowID: Flowd to check in the list
1018 : return true and the index if present false otherwise.
1019 */
1020
1021 for idx, _ := range FlowIDList {
1022 if FlowID == FlowIDList[idx] {
1023 return true, uint32(idx)
1024 }
1025 }
1026 return false, 0
1027}
1028
npujar5bf737f2020-01-16 19:35:25 +05301029func (PONRMgr *PONResourceManager) UpdateFlowIDForOnu(ctx context.Context, IntfONUID string, FlowID uint32, Add bool) error {
Scott Baker2c1c4822019-10-16 11:02:41 -07001030 /*
1031 Update the flow_id list of the ONU (add or remove flow_id from the list)
1032 :param pon_intf_onu_id: reference of PON interface id and onu id
1033 :param flow_id: flow ID
1034 :param add: Boolean flag to indicate whether the flow_id should be
1035 added or removed from the list. Defaults to adding the flow.
1036 */
1037 var Value []byte
1038 var err error
1039 var RetVal bool
1040 var IDx uint32
1041 Path := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
npujar5bf737f2020-01-16 19:35:25 +05301042 FlowIDs := PONRMgr.GetCurrentFlowIDsForOnu(ctx, IntfONUID)
Scott Baker2c1c4822019-10-16 11:02:41 -07001043
1044 if Add {
1045 if RetVal, IDx = checkForFlowIDInList(FlowIDs, FlowID); RetVal == true {
1046 return err
1047 }
1048 FlowIDs = append(FlowIDs, FlowID)
1049 } else {
1050 if RetVal, IDx = checkForFlowIDInList(FlowIDs, FlowID); RetVal == false {
1051 return err
1052 }
1053 // delete the index and shift
1054 FlowIDs = append(FlowIDs[:IDx], FlowIDs[IDx+1:]...)
1055 }
1056 Value, err = json.Marshal(FlowIDs)
1057 if err != nil {
1058 log.Error("Failed to Marshal")
1059 return err
1060 }
1061
npujar5bf737f2020-01-16 19:35:25 +05301062 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Scott Baker2c1c4822019-10-16 11:02:41 -07001063 log.Errorf("Failed to update resource %s", Path)
1064 return err
1065 }
1066 return err
1067}
1068
npujar5bf737f2020-01-16 19:35:25 +05301069func (PONRMgr *PONResourceManager) UpdateFlowIDInfoForOnu(ctx context.Context, IntfONUID string, FlowID uint32, FlowData interface{}) error {
Scott Baker2c1c4822019-10-16 11:02:41 -07001070 /*
1071 Update any metadata associated with the flow_id. The flow_data could be json
1072 or any of other data structure. The resource manager doesnt care
1073 :param pon_intf_onu_id: reference of PON interface id and onu id
1074 :param flow_id: Flow ID
1075 :param flow_data: Flow data blob
1076 */
1077 var Value []byte
1078 var err error
1079 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
1080 Value, err = json.Marshal(FlowData)
1081 if err != nil {
1082 log.Error("failed to Marshal")
1083 return err
1084 }
1085
npujar5bf737f2020-01-16 19:35:25 +05301086 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Scott Baker2c1c4822019-10-16 11:02:41 -07001087 log.Errorf("Failed to update resource %s", Path)
1088 return err
1089 }
1090 return err
1091}
1092
1093func (PONRMgr *PONResourceManager) GenerateNextID(Resource map[string]interface{}) (uint32, error) {
1094 /*
1095 Generate unique id having OFFSET as start
1096 :param resource: resource used to generate ID
1097 :return uint32: generated id
1098 */
1099 ByteArray, err := ToByte(Resource[POOL])
1100 if err != nil {
1101 log.Error("Failed to convert resource to byte array")
1102 return 0, err
1103 }
1104 Data := bitmap.TSFromData(ByteArray, false)
1105 if Data == nil {
1106 log.Error("Failed to get data from byte array")
1107 return 0, errors.New("Failed to get data from byte array")
1108 }
1109
1110 Len := Data.Len()
1111 var Idx int
1112 for Idx = 0; Idx < Len; Idx++ {
1113 Val := Data.Get(Idx)
1114 if Val == false {
1115 break
1116 }
1117 }
1118 Data.Set(Idx, true)
1119 res := uint32(Resource[START_IDX].(float64))
1120 Resource[POOL] = Data.Data(false)
1121 log.Debugf("Generated ID for %d", (uint32(Idx) + res))
1122 return (uint32(Idx) + res), err
1123}
1124
1125func (PONRMgr *PONResourceManager) ReleaseID(Resource map[string]interface{}, Id uint32) bool {
1126 /*
1127 Release unique id having OFFSET as start index.
1128 :param resource: resource used to release ID
1129 :param unique_id: id need to be released
1130 */
1131 ByteArray, err := ToByte(Resource[POOL])
1132 if err != nil {
1133 log.Error("Failed to convert resource to byte array")
1134 return false
1135 }
1136 Data := bitmap.TSFromData(ByteArray, false)
1137 if Data == nil {
1138 log.Error("Failed to get resource pool")
1139 return false
1140 }
1141 var Idx uint32
1142 Idx = Id - uint32(Resource[START_IDX].(float64))
1143 Data.Set(int(Idx), false)
1144 Resource[POOL] = Data.Data(false)
1145
1146 return true
1147}
1148
1149func (PONRMgr *PONResourceManager) GetTechnology() string {
1150 return PONRMgr.Technology
1151}
1152
1153func (PONRMgr *PONResourceManager) GetResourceTypeAllocID() string {
1154 return ALLOC_ID
1155}
1156
1157func (PONRMgr *PONResourceManager) GetResourceTypeGemPortID() string {
1158 return GEMPORT_ID
1159}
1160
1161// ToByte converts an interface value to a []byte. The interface should either be of
1162// a string type or []byte. Otherwise, an error is returned.
1163func ToByte(value interface{}) ([]byte, error) {
1164 switch t := value.(type) {
1165 case []byte:
1166 return value.([]byte), nil
1167 case string:
1168 return []byte(value.(string)), nil
1169 default:
1170 return nil, fmt.Errorf("unexpected-type-%T", t)
1171 }
1172}
1173
1174// ToString converts an interface value to a string. The interface should either be of
1175// a string type or []byte. Otherwise, an error is returned.
1176func ToString(value interface{}) (string, error) {
1177 switch t := value.(type) {
1178 case []byte:
1179 return string(value.([]byte)), nil
1180 case string:
1181 return value.(string), nil
1182 default:
1183 return "", fmt.Errorf("unexpected-type-%T", t)
1184 }
1185}
Abhilash Laxmeshwarbbb0b2b2019-10-31 17:04:29 +05301186
npujar5bf737f2020-01-16 19:35:25 +05301187func (PONRMgr *PONResourceManager) AddOnuGemInfo(ctx context.Context, intfID uint32, onuGemData interface{}) error {
Abhilash Laxmeshwarbbb0b2b2019-10-31 17:04:29 +05301188 /*
1189 Update onugem info map,
1190 :param pon_intf_id: reference of PON interface id
1191 :param onuegmdata: onugem info map
1192 */
1193 var Value []byte
1194 var err error
1195 Path := fmt.Sprintf(ONU_GEM_INFO_PATH, PONRMgr.DeviceID, intfID)
1196 Value, err = json.Marshal(onuGemData)
1197 if err != nil {
1198 log.Error("failed to Marshal")
1199 return err
1200 }
1201
npujar5bf737f2020-01-16 19:35:25 +05301202 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Abhilash Laxmeshwarbbb0b2b2019-10-31 17:04:29 +05301203 log.Errorf("Failed to update resource %s", Path)
1204 return err
1205 }
1206 return err
1207}
1208
npujar5bf737f2020-01-16 19:35:25 +05301209func (PONRMgr *PONResourceManager) GetOnuGemInfo(ctx context.Context, IntfId uint32, onuGemInfo interface{}) error {
Abhilash Laxmeshwarbbb0b2b2019-10-31 17:04:29 +05301210 /*
1211 Get onugeminfo map from kvstore
1212 :param intfid: refremce pon intfid
1213 :param onuGemInfo: onugem info to return from kv strore.
1214 */
1215 var Val []byte
1216
1217 path := fmt.Sprintf(ONU_GEM_INFO_PATH, PONRMgr.DeviceID, IntfId)
npujar5bf737f2020-01-16 19:35:25 +05301218 value, err := PONRMgr.KVStore.Get(ctx, path)
Abhilash Laxmeshwarbbb0b2b2019-10-31 17:04:29 +05301219 if err != nil {
1220 log.Errorw("Failed to get from kv store", log.Fields{"path": path})
1221 return err
1222 } else if value == nil {
1223 log.Debug("No onuinfo for path", log.Fields{"path": path})
1224 return nil // returning nil as this could happen if there are no onus for the interface yet
1225 }
1226 if Val, err = kvstore.ToByte(value.Value); err != nil {
1227 log.Error("Failed to convert to byte array")
1228 return err
1229 }
1230
1231 if err = json.Unmarshal(Val, &onuGemInfo); err != nil {
1232 log.Error("Failed to unmarshall")
1233 return err
1234 }
1235 log.Debugw("found onuinfo from path", log.Fields{"path": path, "onuinfo": onuGemInfo})
1236 return err
1237}
1238
npujar5bf737f2020-01-16 19:35:25 +05301239func (PONRMgr *PONResourceManager) DelOnuGemInfoForIntf(ctx context.Context, intfId uint32) error {
Abhilash Laxmeshwarbbb0b2b2019-10-31 17:04:29 +05301240 /*
1241 delete onugem info for an interface from kvstore
1242 :param intfid: refremce pon intfid
1243 */
1244
1245 path := fmt.Sprintf(ONU_GEM_INFO_PATH, PONRMgr.DeviceID, intfId)
npujar5bf737f2020-01-16 19:35:25 +05301246 if err := PONRMgr.KVStore.Delete(ctx, path); err != nil {
Abhilash Laxmeshwarbbb0b2b2019-10-31 17:04:29 +05301247 log.Errorf("Falied to remove resource %s", path)
1248 return err
1249 }
1250 return nil
1251}