blob: 6ed18e97225d511d9996b22df5dc083c97cc5bcf [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 }
David K. Bainbridge7c75cac2020-02-19 08:53:46 -0800414 if status := PONRMgr.ClearResourceIDPool(ctx, Intf, ONU_ID); !status {
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 }
David K. Bainbridge7c75cac2020-02-19 08:53:46 -0800428 if status := PONRMgr.ClearResourceIDPool(ctx, Intf, ALLOC_ID); !status {
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 }
David K. Bainbridge7c75cac2020-02-19 08:53:46 -0800441 if status := PONRMgr.ClearResourceIDPool(ctx, Intf, GEMPORT_ID); !status {
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 }
David K. Bainbridge7c75cac2020-02-19 08:53:46 -0800455 if status := PONRMgr.ClearResourceIDPool(ctx, Intf, FLOW_ID); !status {
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)
David K. Bainbridge7c75cac2020-02-19 08:53:46 -0800486 return fmt.Errorf("Failed to get path for resource type %s", ResourceType)
Scott Baker2c1c4822019-10-16 11:02:41 -0700487 }
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)
David K. Bainbridge7c75cac2020-02-19 08:53:46 -0800566 if err != nil {
567 return nil, err
568 }
Scott Baker2c1c4822019-10-16 11:02:41 -0700569
570 // decode resource fetched from backend store to dictionary
571 err = json.Unmarshal(Value, &Result)
572 if err != nil {
573 log.Error("Failed to decode resource")
574 return Result, err
575 }
576 /*
577 resource pool in backend store stored as binary string whereas to
578 access the pool to generate/release IDs it need to be converted
579 as BitArray
580 */
581 Str, err = ToString(Result[POOL])
582 if err != nil {
583 log.Error("Failed to conver to kv pair to string")
584 return Result, err
585 }
586 Decode64, _ := base64.StdEncoding.DecodeString(Str)
587 Result[POOL], err = ToByte(Decode64)
588 if err != nil {
589 log.Error("Failed to convert resource pool to byte")
590 return Result, err
591 }
592
593 return Result, err
594}
595
596func (PONRMgr *PONResourceManager) GetPath(IntfID uint32, ResourceType string) string {
597 /*
598 Get path for given resource type.
599 :param pon_intf_id: OLT PON interface id
600 :param resource_type: String to identify type of resource
601 :return: path for given resource type
602 */
603
604 /*
605 Get the shared pool for the given resource type.
606 all the resource ranges and the shared resource maps are initialized during the init.
607 */
608 SharedPoolID := PONRMgr.PonResourceRanges[PONRMgr.SharedIdxByType[ResourceType]].(uint32)
609 if SharedPoolID != 0 {
610 IntfID = SharedPoolID
611 }
612 var Path string
613 if ResourceType == ONU_ID {
614 Path = fmt.Sprintf(ONU_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
615 } else if ResourceType == ALLOC_ID {
616 Path = fmt.Sprintf(ALLOC_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
617 } else if ResourceType == GEMPORT_ID {
618 Path = fmt.Sprintf(GEMPORT_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
619 } else if ResourceType == FLOW_ID {
620 Path = fmt.Sprintf(FLOW_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
621 } else {
622 log.Error("Invalid resource pool identifier")
623 }
624 return Path
625}
626
npujar5bf737f2020-01-16 19:35:25 +0530627func (PONRMgr *PONResourceManager) GetResourceID(ctx context.Context, IntfID uint32, ResourceType string, NumIDs uint32) ([]uint32, error) {
Scott Baker2c1c4822019-10-16 11:02:41 -0700628 /*
629 Create alloc/gemport/onu/flow id for given OLT PON interface.
630 :param pon_intf_id: OLT PON interface id
631 :param resource_type: String to identify type of resource
632 :param num_of_id: required number of ids
633 :return list/uint32/None: list, uint32 or None if resource type is
634 alloc_id/gemport_id, onu_id or invalid type respectively
635 */
636 if NumIDs < 1 {
637 log.Error("Invalid number of resources requested")
David K. Bainbridge7c75cac2020-02-19 08:53:46 -0800638 return nil, fmt.Errorf("Invalid number of resources requested %d", NumIDs)
Scott Baker2c1c4822019-10-16 11:02:41 -0700639 }
640 // delegate to the master instance if sharing enabled across instances
641
642 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
643 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
npujar5bf737f2020-01-16 19:35:25 +0530644 return SharedResourceMgr.GetResourceID(ctx, IntfID, ResourceType, NumIDs)
Scott Baker2c1c4822019-10-16 11:02:41 -0700645 }
646 log.Debugf("Fetching resource from %s rsrc mgr for resource %s", PONRMgr.Globalorlocal, ResourceType)
647
648 Path := PONRMgr.GetPath(IntfID, ResourceType)
649 if Path == "" {
650 log.Errorf("Failed to get path for resource type %s", ResourceType)
David K. Bainbridge7c75cac2020-02-19 08:53:46 -0800651 return nil, fmt.Errorf("Failed to get path for resource type %s", ResourceType)
Scott Baker2c1c4822019-10-16 11:02:41 -0700652 }
653 log.Debugf("Get resource for type %s on path %s", ResourceType, Path)
654 var Result []uint32
655 var NextID uint32
npujar5bf737f2020-01-16 19:35:25 +0530656 Resource, err := PONRMgr.GetResource(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700657 if (err == nil) && (ResourceType == ONU_ID) || (ResourceType == FLOW_ID) {
658 if NextID, err = PONRMgr.GenerateNextID(Resource); err != nil {
659 log.Error("Failed to Generate ID")
660 return Result, err
661 }
662 Result = append(Result, NextID)
663 } else if (err == nil) && ((ResourceType == GEMPORT_ID) || (ResourceType == ALLOC_ID)) {
664 if NumIDs == 1 {
665 if NextID, err = PONRMgr.GenerateNextID(Resource); err != nil {
666 log.Error("Failed to Generate ID")
667 return Result, err
668 }
669 Result = append(Result, NextID)
670 } else {
671 for NumIDs > 0 {
672 if NextID, err = PONRMgr.GenerateNextID(Resource); err != nil {
673 log.Error("Failed to Generate ID")
674 return Result, err
675 }
676 Result = append(Result, NextID)
677 NumIDs--
678 }
679 }
680 } else {
681 log.Error("get resource failed")
682 return Result, err
683 }
684
685 //Update resource in kv store
npujar5bf737f2020-01-16 19:35:25 +0530686 if PONRMgr.UpdateResource(ctx, Path, Resource) != nil {
Scott Baker2c1c4822019-10-16 11:02:41 -0700687 log.Errorf("Failed to update resource %s", Path)
David K. Bainbridge7c75cac2020-02-19 08:53:46 -0800688 return nil, fmt.Errorf("Failed to update resource %s", Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700689 }
690 return Result, nil
691}
692
693func checkValidResourceType(ResourceType string) bool {
694 KnownResourceTypes := []string{ONU_ID, ALLOC_ID, GEMPORT_ID, FLOW_ID}
695
696 for _, v := range KnownResourceTypes {
697 if v == ResourceType {
698 return true
699 }
700 }
701 return false
702}
703
npujar5bf737f2020-01-16 19:35:25 +0530704func (PONRMgr *PONResourceManager) FreeResourceID(ctx context.Context, IntfID uint32, ResourceType string, ReleaseContent []uint32) bool {
Scott Baker2c1c4822019-10-16 11:02:41 -0700705 /*
706 Release alloc/gemport/onu/flow id for given OLT PON interface.
707 :param pon_intf_id: OLT PON interface id
708 :param resource_type: String to identify type of resource
709 :param release_content: required number of ids
710 :return boolean: True if all IDs in given release_content release else False
711 */
David K. Bainbridge7c75cac2020-02-19 08:53:46 -0800712 if !checkValidResourceType(ResourceType) {
Scott Baker2c1c4822019-10-16 11:02:41 -0700713 log.Error("Invalid resource type")
714 return false
715 }
716 if ReleaseContent == nil {
717 log.Debug("Nothing to release")
718 return true
719 }
720 // delegate to the master instance if sharing enabled across instances
721 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
722 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
npujar5bf737f2020-01-16 19:35:25 +0530723 return SharedResourceMgr.FreeResourceID(ctx, IntfID, ResourceType, ReleaseContent)
Scott Baker2c1c4822019-10-16 11:02:41 -0700724 }
725 Path := PONRMgr.GetPath(IntfID, ResourceType)
726 if Path == "" {
727 log.Error("Failed to get path")
728 return false
729 }
npujar5bf737f2020-01-16 19:35:25 +0530730 Resource, err := PONRMgr.GetResource(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700731 if err != nil {
732 log.Error("Failed to get resource")
733 return false
734 }
735 for _, Val := range ReleaseContent {
736 PONRMgr.ReleaseID(Resource, Val)
737 }
npujar5bf737f2020-01-16 19:35:25 +0530738 if PONRMgr.UpdateResource(ctx, Path, Resource) != nil {
Scott Baker2c1c4822019-10-16 11:02:41 -0700739 log.Errorf("Free resource for %s failed", Path)
740 return false
741 }
742 return true
743}
744
npujar5bf737f2020-01-16 19:35:25 +0530745func (PONRMgr *PONResourceManager) UpdateResource(ctx context.Context, Path string, Resource map[string]interface{}) error {
Scott Baker2c1c4822019-10-16 11:02:41 -0700746 /*
747 Update resource in resource kv store.
748 :param path: path to update resource
749 :param resource: resource need to be updated
750 :return boolean: True if resource updated in kv store else False
751 */
752 // TODO resource[POOL] = resource[POOL].bin
753 Value, err := json.Marshal(Resource)
754 if err != nil {
755 log.Error("failed to Marshal")
756 return err
757 }
npujar5bf737f2020-01-16 19:35:25 +0530758 err = PONRMgr.KVStore.Put(ctx, Path, Value)
Scott Baker2c1c4822019-10-16 11:02:41 -0700759 if err != nil {
760 log.Error("failed to put data to kv store %s", Path)
761 return err
762 }
763 return nil
764}
765
npujar5bf737f2020-01-16 19:35:25 +0530766func (PONRMgr *PONResourceManager) ClearResourceIDPool(ctx context.Context, contIntfID uint32, ResourceType string) bool {
Scott Baker2c1c4822019-10-16 11:02:41 -0700767 /*
768 Clear Resource Pool for a given Resource Type on a given PON Port.
769 :return boolean: True if removed else False
770 */
771
772 // delegate to the master instance if sharing enabled across instances
773 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
774 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
npujar5bf737f2020-01-16 19:35:25 +0530775 return SharedResourceMgr.ClearResourceIDPool(ctx, contIntfID, ResourceType)
Scott Baker2c1c4822019-10-16 11:02:41 -0700776 }
npujar5bf737f2020-01-16 19:35:25 +0530777 Path := PONRMgr.GetPath(contIntfID, ResourceType)
Scott Baker2c1c4822019-10-16 11:02:41 -0700778 if Path == "" {
779 log.Error("Failed to get path")
780 return false
781 }
782
npujar5bf737f2020-01-16 19:35:25 +0530783 if err := PONRMgr.KVStore.Delete(ctx, Path); err != nil {
Scott Baker2c1c4822019-10-16 11:02:41 -0700784 log.Errorf("Failed to delete resource %s", Path)
785 return false
786 }
787 log.Debugf("Cleared resource %s", Path)
788 return true
789}
790
npujar5bf737f2020-01-16 19:35:25 +0530791func (PONRMgr PONResourceManager) InitResourceMap(ctx context.Context, PONIntfONUID string) {
Scott Baker2c1c4822019-10-16 11:02:41 -0700792 /*
793 Initialize resource map
794 :param pon_intf_onu_id: reference of PON interface id and onu id
795 */
796 // initialize pon_intf_onu_id tuple to alloc_ids map
797 AllocIDPath := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
798 var AllocIDs []byte
npujar5bf737f2020-01-16 19:35:25 +0530799 Result := PONRMgr.KVStore.Put(ctx, AllocIDPath, AllocIDs)
Scott Baker2c1c4822019-10-16 11:02:41 -0700800 if Result != nil {
801 log.Error("Failed to update the KV store")
802 return
803 }
804 // initialize pon_intf_onu_id tuple to gemport_ids map
805 GEMPortIDPath := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
806 var GEMPortIDs []byte
npujar5bf737f2020-01-16 19:35:25 +0530807 Result = PONRMgr.KVStore.Put(ctx, GEMPortIDPath, GEMPortIDs)
Scott Baker2c1c4822019-10-16 11:02:41 -0700808 if Result != nil {
809 log.Error("Failed to update the KV store")
810 return
811 }
812}
813
npujar5bf737f2020-01-16 19:35:25 +0530814func (PONRMgr PONResourceManager) RemoveResourceMap(ctx context.Context, PONIntfONUID string) bool {
Scott Baker2c1c4822019-10-16 11:02:41 -0700815 /*
816 Remove resource map
817 :param pon_intf_onu_id: reference of PON interface id and onu id
818 */
819 // remove pon_intf_onu_id tuple to alloc_ids map
820 var err error
821 AllocIDPath := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
npujar5bf737f2020-01-16 19:35:25 +0530822 if err = PONRMgr.KVStore.Delete(ctx, AllocIDPath); err != nil {
Scott Baker2c1c4822019-10-16 11:02:41 -0700823 log.Errorf("Failed to remove resource %s", AllocIDPath)
824 return false
825 }
826 // remove pon_intf_onu_id tuple to gemport_ids map
827 GEMPortIDPath := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
npujar5bf737f2020-01-16 19:35:25 +0530828 err = PONRMgr.KVStore.Delete(ctx, GEMPortIDPath)
Scott Baker2c1c4822019-10-16 11:02:41 -0700829 if err != nil {
830 log.Errorf("Failed to remove resource %s", GEMPortIDPath)
831 return false
832 }
833
834 FlowIDPath := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
npujar5bf737f2020-01-16 19:35:25 +0530835 if FlowIDs, err := PONRMgr.KVStore.List(ctx, FlowIDPath); err != nil {
Scott Baker2c1c4822019-10-16 11:02:41 -0700836 for _, Flow := range FlowIDs {
837 FlowIDInfoPath := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, PONIntfONUID, Flow.Value)
npujar5bf737f2020-01-16 19:35:25 +0530838 if err = PONRMgr.KVStore.Delete(ctx, FlowIDInfoPath); err != nil {
Scott Baker2c1c4822019-10-16 11:02:41 -0700839 log.Errorf("Failed to remove resource %s", FlowIDInfoPath)
840 return false
841 }
842 }
843 }
844
npujar5bf737f2020-01-16 19:35:25 +0530845 if err = PONRMgr.KVStore.Delete(ctx, FlowIDPath); err != nil {
Scott Baker2c1c4822019-10-16 11:02:41 -0700846 log.Errorf("Failed to remove resource %s", FlowIDPath)
847 return false
848 }
849
850 return true
851}
852
npujar5bf737f2020-01-16 19:35:25 +0530853func (PONRMgr *PONResourceManager) GetCurrentAllocIDForOnu(ctx context.Context, IntfONUID string) []uint32 {
Scott Baker2c1c4822019-10-16 11:02:41 -0700854 /*
855 Get currently configured alloc ids for given pon_intf_onu_id
856 :param pon_intf_onu_id: reference of PON interface id and onu id
857 :return list: List of alloc_ids if available, else None
858 */
859 Path := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
860
861 var Data []uint32
npujar5bf737f2020-01-16 19:35:25 +0530862 Value, err := PONRMgr.KVStore.Get(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700863 if err == nil {
864 if Value != nil {
865 Val, err := ToByte(Value.Value)
866 if err != nil {
867 log.Errorw("Failed to convert into byte array", log.Fields{"error": err})
868 return Data
869 }
870 if err = json.Unmarshal(Val, &Data); err != nil {
871 log.Error("Failed to unmarshal", log.Fields{"error": err})
872 return Data
873 }
874 }
875 }
876 return Data
877}
878
npujar5bf737f2020-01-16 19:35:25 +0530879func (PONRMgr *PONResourceManager) GetCurrentGEMPortIDsForOnu(ctx context.Context, IntfONUID string) []uint32 {
Scott Baker2c1c4822019-10-16 11:02:41 -0700880 /*
881 Get currently configured gemport ids for given pon_intf_onu_id
882 :param pon_intf_onu_id: reference of PON interface id and onu id
883 :return list: List of gemport IDs if available, else None
884 */
885
886 Path := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
887 log.Debugf("Getting current gemports for %s", Path)
888 var Data []uint32
npujar5bf737f2020-01-16 19:35:25 +0530889 Value, err := PONRMgr.KVStore.Get(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700890 if err == nil {
891 if Value != nil {
892 Val, _ := ToByte(Value.Value)
893 if err = json.Unmarshal(Val, &Data); err != nil {
894 log.Errorw("Failed to unmarshal", log.Fields{"error": err})
895 return Data
896 }
897 }
898 } else {
899 log.Errorf("Failed to get data from kvstore for %s", Path)
900 }
901 return Data
902}
903
npujar5bf737f2020-01-16 19:35:25 +0530904func (PONRMgr *PONResourceManager) GetCurrentFlowIDsForOnu(ctx context.Context, IntfONUID string) []uint32 {
Scott Baker2c1c4822019-10-16 11:02:41 -0700905 /*
906 Get currently configured flow ids for given pon_intf_onu_id
907 :param pon_intf_onu_id: reference of PON interface id and onu id
908 :return list: List of Flow IDs if available, else None
909 */
910
911 Path := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
912
913 var Data []uint32
npujar5bf737f2020-01-16 19:35:25 +0530914 Value, err := PONRMgr.KVStore.Get(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700915 if err == nil {
916 if Value != nil {
917 Val, _ := ToByte(Value.Value)
918 if err = json.Unmarshal(Val, &Data); err != nil {
919 log.Error("Failed to unmarshal")
920 return Data
921 }
922 }
923 }
924 return Data
925}
926
npujar5bf737f2020-01-16 19:35:25 +0530927func (PONRMgr *PONResourceManager) GetFlowIDInfo(ctx context.Context, IntfONUID string, FlowID uint32, Data interface{}) error {
Scott Baker2c1c4822019-10-16 11:02:41 -0700928 /*
929 Get flow details configured for the ONU.
930 :param pon_intf_onu_id: reference of PON interface id and onu id
931 :param flow_id: Flow Id reference
932 :param Data: Result
933 :return error: nil if no error in getting from KV store
934 */
935
936 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
937
npujar5bf737f2020-01-16 19:35:25 +0530938 Value, err := PONRMgr.KVStore.Get(ctx, Path)
Scott Baker2c1c4822019-10-16 11:02:41 -0700939 if err == nil {
940 if Value != nil {
941 Val, err := ToByte(Value.Value)
942 if err != nil {
943 log.Errorw("Failed to convert flowinfo into byte array", log.Fields{"error": err})
944 return err
945 }
946 if err = json.Unmarshal(Val, Data); err != nil {
947 log.Errorw("Failed to unmarshal", log.Fields{"error": err})
948 return err
949 }
950 }
951 }
952 return err
953}
954
npujar5bf737f2020-01-16 19:35:25 +0530955func (PONRMgr *PONResourceManager) RemoveFlowIDInfo(ctx context.Context, IntfONUID string, FlowID uint32) bool {
Scott Baker2c1c4822019-10-16 11:02:41 -0700956 /*
957 Get flow_id details configured for the ONU.
958 :param pon_intf_onu_id: reference of PON interface id and onu id
959 :param flow_id: Flow Id reference
960 */
961 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
962
npujar5bf737f2020-01-16 19:35:25 +0530963 if err := PONRMgr.KVStore.Delete(ctx, Path); err != nil {
Scott Baker2c1c4822019-10-16 11:02:41 -0700964 log.Errorf("Falied to remove resource %s", Path)
965 return false
966 }
967 return true
968}
969
npujar5bf737f2020-01-16 19:35:25 +0530970func (PONRMgr *PONResourceManager) UpdateAllocIdsForOnu(ctx context.Context, IntfONUID string, AllocIDs []uint32) error {
Scott Baker2c1c4822019-10-16 11:02:41 -0700971 /*
972 Update currently configured alloc ids for given pon_intf_onu_id
973 :param pon_intf_onu_id: reference of PON interface id and onu id
974 :param alloc_ids: list of alloc ids
975 */
976 var Value []byte
977 var err error
978 Path := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
979 Value, err = json.Marshal(AllocIDs)
980 if err != nil {
981 log.Error("failed to Marshal")
982 return err
983 }
984
npujar5bf737f2020-01-16 19:35:25 +0530985 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Scott Baker2c1c4822019-10-16 11:02:41 -0700986 log.Errorf("Failed to update resource %s", Path)
987 return err
988 }
989 return err
990}
991
npujar5bf737f2020-01-16 19:35:25 +0530992func (PONRMgr *PONResourceManager) UpdateGEMPortIDsForOnu(ctx context.Context, IntfONUID string, GEMPortIDs []uint32) error {
Scott Baker2c1c4822019-10-16 11:02:41 -0700993 /*
994 Update currently configured gemport ids for given pon_intf_onu_id
995 :param pon_intf_onu_id: reference of PON interface id and onu id
996 :param gemport_ids: list of gem port ids
997 */
998
999 var Value []byte
1000 var err error
1001 Path := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
1002 log.Debugf("Updating gemport ids for %s", Path)
1003 Value, err = json.Marshal(GEMPortIDs)
1004 if err != nil {
1005 log.Error("failed to Marshal")
1006 return err
1007 }
1008
npujar5bf737f2020-01-16 19:35:25 +05301009 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Scott Baker2c1c4822019-10-16 11:02:41 -07001010 log.Errorf("Failed to update resource %s", Path)
1011 return err
1012 }
1013 return err
1014}
1015
1016func checkForFlowIDInList(FlowIDList []uint32, FlowID uint32) (bool, uint32) {
1017 /*
1018 Check for a flow id in a given list of flow IDs.
1019 :param FLowIDList: List of Flow IDs
1020 :param FlowID: Flowd to check in the list
1021 : return true and the index if present false otherwise.
1022 */
1023
David K. Bainbridge7c75cac2020-02-19 08:53:46 -08001024 for idx := range FlowIDList {
Scott Baker2c1c4822019-10-16 11:02:41 -07001025 if FlowID == FlowIDList[idx] {
1026 return true, uint32(idx)
1027 }
1028 }
1029 return false, 0
1030}
1031
npujar5bf737f2020-01-16 19:35:25 +05301032func (PONRMgr *PONResourceManager) UpdateFlowIDForOnu(ctx context.Context, IntfONUID string, FlowID uint32, Add bool) error {
Scott Baker2c1c4822019-10-16 11:02:41 -07001033 /*
1034 Update the flow_id list of the ONU (add or remove flow_id from the list)
1035 :param pon_intf_onu_id: reference of PON interface id and onu id
1036 :param flow_id: flow ID
1037 :param add: Boolean flag to indicate whether the flow_id should be
1038 added or removed from the list. Defaults to adding the flow.
1039 */
1040 var Value []byte
1041 var err error
1042 var RetVal bool
1043 var IDx uint32
1044 Path := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
npujar5bf737f2020-01-16 19:35:25 +05301045 FlowIDs := PONRMgr.GetCurrentFlowIDsForOnu(ctx, IntfONUID)
Scott Baker2c1c4822019-10-16 11:02:41 -07001046
1047 if Add {
David K. Bainbridge7c75cac2020-02-19 08:53:46 -08001048 if RetVal, _ = checkForFlowIDInList(FlowIDs, FlowID); RetVal {
1049 return nil
Scott Baker2c1c4822019-10-16 11:02:41 -07001050 }
1051 FlowIDs = append(FlowIDs, FlowID)
1052 } else {
David K. Bainbridge7c75cac2020-02-19 08:53:46 -08001053 if RetVal, IDx = checkForFlowIDInList(FlowIDs, FlowID); !RetVal {
1054 return nil
Scott Baker2c1c4822019-10-16 11:02:41 -07001055 }
1056 // delete the index and shift
1057 FlowIDs = append(FlowIDs[:IDx], FlowIDs[IDx+1:]...)
1058 }
1059 Value, err = json.Marshal(FlowIDs)
1060 if err != nil {
1061 log.Error("Failed to Marshal")
1062 return err
1063 }
1064
npujar5bf737f2020-01-16 19:35:25 +05301065 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Scott Baker2c1c4822019-10-16 11:02:41 -07001066 log.Errorf("Failed to update resource %s", Path)
1067 return err
1068 }
1069 return err
1070}
1071
npujar5bf737f2020-01-16 19:35:25 +05301072func (PONRMgr *PONResourceManager) UpdateFlowIDInfoForOnu(ctx context.Context, IntfONUID string, FlowID uint32, FlowData interface{}) error {
Scott Baker2c1c4822019-10-16 11:02:41 -07001073 /*
1074 Update any metadata associated with the flow_id. The flow_data could be json
1075 or any of other data structure. The resource manager doesnt care
1076 :param pon_intf_onu_id: reference of PON interface id and onu id
1077 :param flow_id: Flow ID
1078 :param flow_data: Flow data blob
1079 */
1080 var Value []byte
1081 var err error
1082 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
1083 Value, err = json.Marshal(FlowData)
1084 if err != nil {
1085 log.Error("failed to Marshal")
1086 return err
1087 }
1088
npujar5bf737f2020-01-16 19:35:25 +05301089 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Scott Baker2c1c4822019-10-16 11:02:41 -07001090 log.Errorf("Failed to update resource %s", Path)
1091 return err
1092 }
1093 return err
1094}
1095
1096func (PONRMgr *PONResourceManager) GenerateNextID(Resource map[string]interface{}) (uint32, error) {
1097 /*
1098 Generate unique id having OFFSET as start
1099 :param resource: resource used to generate ID
1100 :return uint32: generated id
1101 */
1102 ByteArray, err := ToByte(Resource[POOL])
1103 if err != nil {
1104 log.Error("Failed to convert resource to byte array")
1105 return 0, err
1106 }
1107 Data := bitmap.TSFromData(ByteArray, false)
1108 if Data == nil {
1109 log.Error("Failed to get data from byte array")
1110 return 0, errors.New("Failed to get data from byte array")
1111 }
1112
1113 Len := Data.Len()
1114 var Idx int
1115 for Idx = 0; Idx < Len; Idx++ {
David K. Bainbridge7c75cac2020-02-19 08:53:46 -08001116 if !Data.Get(Idx) {
Scott Baker2c1c4822019-10-16 11:02:41 -07001117 break
1118 }
1119 }
1120 Data.Set(Idx, true)
1121 res := uint32(Resource[START_IDX].(float64))
1122 Resource[POOL] = Data.Data(false)
1123 log.Debugf("Generated ID for %d", (uint32(Idx) + res))
1124 return (uint32(Idx) + res), err
1125}
1126
1127func (PONRMgr *PONResourceManager) ReleaseID(Resource map[string]interface{}, Id uint32) bool {
1128 /*
1129 Release unique id having OFFSET as start index.
1130 :param resource: resource used to release ID
1131 :param unique_id: id need to be released
1132 */
1133 ByteArray, err := ToByte(Resource[POOL])
1134 if err != nil {
1135 log.Error("Failed to convert resource to byte array")
1136 return false
1137 }
1138 Data := bitmap.TSFromData(ByteArray, false)
1139 if Data == nil {
1140 log.Error("Failed to get resource pool")
1141 return false
1142 }
David K. Bainbridge7c75cac2020-02-19 08:53:46 -08001143 Idx := Id - uint32(Resource[START_IDX].(float64))
Scott Baker2c1c4822019-10-16 11:02:41 -07001144 Data.Set(int(Idx), false)
1145 Resource[POOL] = Data.Data(false)
1146
1147 return true
1148}
1149
1150func (PONRMgr *PONResourceManager) GetTechnology() string {
1151 return PONRMgr.Technology
1152}
1153
1154func (PONRMgr *PONResourceManager) GetResourceTypeAllocID() string {
1155 return ALLOC_ID
1156}
1157
1158func (PONRMgr *PONResourceManager) GetResourceTypeGemPortID() string {
1159 return GEMPORT_ID
1160}
1161
1162// ToByte converts an interface value to a []byte. The interface should either be of
1163// a string type or []byte. Otherwise, an error is returned.
1164func ToByte(value interface{}) ([]byte, error) {
1165 switch t := value.(type) {
1166 case []byte:
1167 return value.([]byte), nil
1168 case string:
1169 return []byte(value.(string)), nil
1170 default:
1171 return nil, fmt.Errorf("unexpected-type-%T", t)
1172 }
1173}
1174
1175// ToString converts an interface value to a string. The interface should either be of
1176// a string type or []byte. Otherwise, an error is returned.
1177func ToString(value interface{}) (string, error) {
1178 switch t := value.(type) {
1179 case []byte:
1180 return string(value.([]byte)), nil
1181 case string:
1182 return value.(string), nil
1183 default:
1184 return "", fmt.Errorf("unexpected-type-%T", t)
1185 }
1186}
Abhilash Laxmeshwarbbb0b2b2019-10-31 17:04:29 +05301187
npujar5bf737f2020-01-16 19:35:25 +05301188func (PONRMgr *PONResourceManager) AddOnuGemInfo(ctx context.Context, intfID uint32, onuGemData interface{}) error {
Abhilash Laxmeshwarbbb0b2b2019-10-31 17:04:29 +05301189 /*
1190 Update onugem info map,
1191 :param pon_intf_id: reference of PON interface id
1192 :param onuegmdata: onugem info map
1193 */
1194 var Value []byte
1195 var err error
1196 Path := fmt.Sprintf(ONU_GEM_INFO_PATH, PONRMgr.DeviceID, intfID)
1197 Value, err = json.Marshal(onuGemData)
1198 if err != nil {
1199 log.Error("failed to Marshal")
1200 return err
1201 }
1202
npujar5bf737f2020-01-16 19:35:25 +05301203 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Abhilash Laxmeshwarbbb0b2b2019-10-31 17:04:29 +05301204 log.Errorf("Failed to update resource %s", Path)
1205 return err
1206 }
1207 return err
1208}
1209
npujar5bf737f2020-01-16 19:35:25 +05301210func (PONRMgr *PONResourceManager) GetOnuGemInfo(ctx context.Context, IntfId uint32, onuGemInfo interface{}) error {
Abhilash Laxmeshwarbbb0b2b2019-10-31 17:04:29 +05301211 /*
1212 Get onugeminfo map from kvstore
1213 :param intfid: refremce pon intfid
1214 :param onuGemInfo: onugem info to return from kv strore.
1215 */
1216 var Val []byte
1217
1218 path := fmt.Sprintf(ONU_GEM_INFO_PATH, PONRMgr.DeviceID, IntfId)
npujar5bf737f2020-01-16 19:35:25 +05301219 value, err := PONRMgr.KVStore.Get(ctx, path)
Abhilash Laxmeshwarbbb0b2b2019-10-31 17:04:29 +05301220 if err != nil {
1221 log.Errorw("Failed to get from kv store", log.Fields{"path": path})
1222 return err
1223 } else if value == nil {
1224 log.Debug("No onuinfo for path", log.Fields{"path": path})
1225 return nil // returning nil as this could happen if there are no onus for the interface yet
1226 }
1227 if Val, err = kvstore.ToByte(value.Value); err != nil {
1228 log.Error("Failed to convert to byte array")
1229 return err
1230 }
1231
1232 if err = json.Unmarshal(Val, &onuGemInfo); err != nil {
1233 log.Error("Failed to unmarshall")
1234 return err
1235 }
1236 log.Debugw("found onuinfo from path", log.Fields{"path": path, "onuinfo": onuGemInfo})
1237 return err
1238}
1239
npujar5bf737f2020-01-16 19:35:25 +05301240func (PONRMgr *PONResourceManager) DelOnuGemInfoForIntf(ctx context.Context, intfId uint32) error {
Abhilash Laxmeshwarbbb0b2b2019-10-31 17:04:29 +05301241 /*
1242 delete onugem info for an interface from kvstore
1243 :param intfid: refremce pon intfid
1244 */
1245
1246 path := fmt.Sprintf(ONU_GEM_INFO_PATH, PONRMgr.DeviceID, intfId)
npujar5bf737f2020-01-16 19:35:25 +05301247 if err := PONRMgr.KVStore.Delete(ctx, path); err != nil {
Abhilash Laxmeshwarbbb0b2b2019-10-31 17:04:29 +05301248 log.Errorf("Falied to remove resource %s", path)
1249 return err
1250 }
1251 return nil
1252}