blob: ad2150ade73872edac4c1e2fbc13e13a6de4603f [file] [log] [blame]
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001/*
2 * Copyright 2019-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package ponresourcemanager
18
19import (
npujarec5762e2020-01-01 14:08:48 +053020 "context"
Matt Jeanneret384d8c92019-05-06 14:27:31 -040021 "encoding/base64"
22 "encoding/json"
23 "errors"
24 "fmt"
25 "strconv"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040026
Esin Karamanccb714b2019-11-29 15:02:06 +000027 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"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040032)
33
34const (
Matt Jeanneret384d8c92019-05-06 14:27:31 -040035 //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"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040041
Matt Jeanneret384d8c92019-05-06 14:27:31 -040042 //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"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040069
Matt Jeanneret384d8c92019-05-06 14:27:31 -040070 /*
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"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040075
Matt Jeanneret384d8c92019-05-06 14:27:31 -040076 //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}"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040089
Matt Jeanneret384d8c92019-05-06 14:27:31 -040090 //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"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040093
Matt Jeanneret384d8c92019-05-06 14:27:31 -040094 //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"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040097
Matt Jeanneret384d8c92019-05-06 14:27:31 -040098 //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"
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400101
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400102 //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}"
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400105
Scott Bakerc6e54cb2019-11-04 09:31:25 -0800106 //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
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400110 //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
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400116
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400117 KVSTORE_RETRY_TIMEOUT = 5
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400118)
119
120//type ResourceTypeIndex string
121//type ResourceType string
122
123type PONResourceManager struct {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400124 //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
sbarbaria8910ba2019-11-05 10:12:23 -0500132 KVStore *db.Backend
kdarapub26b4502019-10-05 03:02:33 +0530133 TechProfileMgr tp.TechProfileIf // create object of *tp.TechProfileMgr
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400134
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400135 // 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
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400141 Globalorlocal string
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400142}
143
144func newKVClient(storeType string, address string, timeout int) (kvstore.Client, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400145 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")
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400153}
154
sbarbaria8910ba2019-11-05 10:12:23 -0500155func SetKVClient(Technology string, Backend string, Host string, Port int) *db.Backend {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400156 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 }
sbarbaria8910ba2019-11-05 10:12:23 -0500164 kvbackend := &db.Backend{
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400165 Client: kvClient,
166 StoreType: Backend,
167 Host: Host,
168 Port: Port,
169 Timeout: KVSTORE_RETRY_TIMEOUT,
170 PathPrefix: fmt.Sprintf(PATH_PREFIX, Technology)}
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400171
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400172 return kvbackend
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400173}
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) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400177 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
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400190 if PONMgr.TechProfileMgr, _ = tp.NewTechProfile(&PONMgr, Backend, Host, Port); PONMgr.TechProfileMgr == nil {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400191 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
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400204}
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
npujarec5762e2020-01-01 14:08:48 +0530213func (PONRMgr *PONResourceManager) InitResourceRangesFromKVStore(ctx context.Context) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400214 //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
npujarec5762e2020-01-01 14:08:48 +0530224 Result, err := PONRMgr.KVStore.Get(ctx, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400225 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
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400246}
247
248func (PONRMgr *PONResourceManager) UpdateRanges(StartIDx string, StartID uint32, EndIDx string, EndID uint32,
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400249 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)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400261
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400262 if StartID != 0 {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400263 if (PONRMgr.PonResourceRanges[StartIDx] == nil) || (PONRMgr.PonResourceRanges[StartIDx].(uint32) < StartID) {
264 PONRMgr.PonResourceRanges[StartIDx] = StartID
265 }
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400266 }
267 if EndID != 0 {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400268 if (PONRMgr.PonResourceRanges[EndIDx] == nil) || (PONRMgr.PonResourceRanges[EndIDx].(uint32) > EndID) {
269 PONRMgr.PonResourceRanges[EndIDx] = EndID
270 }
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400271 }
272 //if SharedPoolID != 0 {
273 PONRMgr.PonResourceRanges[SharedIDx] = SharedPoolID
274 //}
275 if RMgr != nil {
276 PONRMgr.SharedResourceMgrs[SharedIDx] = RMgr
277 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400278}
279
280func (PONRMgr *PONResourceManager) InitDefaultPONResourceRanges(ONUIDStart uint32,
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400281 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 {
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400296
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400297 /*Initialize default PON resource ranges
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400298
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400299 :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
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400329}
330
npujarec5762e2020-01-01 14:08:48 +0530331func (PONRMgr *PONResourceManager) InitDeviceResourcePool(ctx context.Context) error {
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400332
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400333 //Initialize resource pool for all PON ports.
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400334
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400335 log.Debug("Init resource ranges")
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400336
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400337 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 }
npujarec5762e2020-01-01 14:08:48 +0530343 if err = PONRMgr.InitResourceIDPool(ctx, Intf, ONU_ID,
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400344 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 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400353
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400354 for _, Intf := range PONRMgr.IntfIDs {
355 SharedPoolID := PONRMgr.PonResourceRanges[ALLOC_ID_SHARED_IDX].(uint32)
356 if SharedPoolID != 0 {
357 Intf = SharedPoolID
358 }
npujarec5762e2020-01-01 14:08:48 +0530359 if err = PONRMgr.InitResourceIDPool(ctx, Intf, ALLOC_ID,
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400360 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 }
npujarec5762e2020-01-01 14:08:48 +0530374 if err = PONRMgr.InitResourceIDPool(ctx, Intf, GEMPORT_ID,
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400375 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 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400384
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400385 for _, Intf := range PONRMgr.IntfIDs {
386 SharedPoolID := PONRMgr.PonResourceRanges[FLOW_ID_SHARED_IDX].(uint32)
387 if SharedPoolID != 0 {
388 Intf = SharedPoolID
389 }
npujarec5762e2020-01-01 14:08:48 +0530390 if err = PONRMgr.InitResourceIDPool(ctx, Intf, FLOW_ID,
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400391 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
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400401}
402
npujarec5762e2020-01-01 14:08:48 +0530403func (PONRMgr *PONResourceManager) ClearDeviceResourcePool(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -0400404
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 }
npujarec5762e2020-01-01 14:08:48 +0530414 if status := PONRMgr.ClearResourceIDPool(ctx, Intf, ONU_ID); status != true {
Devmalya Paul495b94a2019-08-27 19:42:00 -0400415 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 }
npujarec5762e2020-01-01 14:08:48 +0530428 if status := PONRMgr.ClearResourceIDPool(ctx, Intf, ALLOC_ID); status != true {
Devmalya Paul495b94a2019-08-27 19:42:00 -0400429 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 }
npujarec5762e2020-01-01 14:08:48 +0530441 if status := PONRMgr.ClearResourceIDPool(ctx, Intf, GEMPORT_ID); status != true {
Devmalya Paul495b94a2019-08-27 19:42:00 -0400442 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 }
npujarec5762e2020-01-01 14:08:48 +0530455 if status := PONRMgr.ClearResourceIDPool(ctx, Intf, FLOW_ID); status != true {
Devmalya Paul495b94a2019-08-27 19:42:00 -0400456 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
npujarec5762e2020-01-01 14:08:48 +0530466func (PONRMgr *PONResourceManager) InitResourceIDPool(ctx context.Context, Intf uint32, ResourceType string, StartID uint32, EndID uint32) error {
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400467
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400468 /*Initialize Resource ID pool for a given Resource Type on a given PON Port
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400469
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400470 :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 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400476
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400477 // delegate to the master instance if sharing enabled across instances
478 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
479 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
npujarec5762e2020-01-01 14:08:48 +0530480 return SharedResourceMgr.InitResourceIDPool(ctx, Intf, ResourceType, StartID, EndID)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400481 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400482
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400483 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 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400488
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400489 //In case of adapter reboot and reconciliation resource in kv store
490 //checked for its presence if not kv store update happens
npujarec5762e2020-01-01 14:08:48 +0530491 Res, err := PONRMgr.GetResource(ctx, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400492 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.
npujarec5762e2020-01-01 14:08:48 +0530502 err = PONRMgr.KVStore.Put(ctx, Path, FormatResult)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400503 if err == nil {
504 log.Debug("Successfuly posted to kv store")
505 return err
506 }
507 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400508
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400509 log.Debug("Error initializing pool")
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400510
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400511 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400512}
513
514func (PONRMgr *PONResourceManager) FormatResource(IntfID uint32, StartIDx uint32, EndIDx uint32) ([]byte, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400515 /*
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
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400538
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400539 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
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400545}
npujarec5762e2020-01-01 14:08:48 +0530546func (PONRMgr *PONResourceManager) GetResource(ctx context.Context, Path string) (map[string]interface{}, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400547 /*
548 Get resource from kv store.
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400549
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400550 :param path: path to get resource
551 :return: resource if resource present in kv store else None
552 */
553 //get resource from kv store
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400554
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400555 var Value []byte
556 Result := make(map[string]interface{})
557 var Str string
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400558
npujarec5762e2020-01-01 14:08:48 +0530559 Resource, err := PONRMgr.KVStore.Get(ctx, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400560 if (err != nil) || (Resource == nil) {
561 log.Debugf("Resource unavailable at %s", Path)
562 return nil, err
563 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400564
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400565 Value, err = ToByte(Resource.Value)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400566
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400567 // 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 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400589
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400590 return Result, err
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400591}
592
593func (PONRMgr *PONResourceManager) GetPath(IntfID uint32, ResourceType string) string {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400594 /*
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 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400600
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400601 /*
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
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400622}
623
npujarec5762e2020-01-01 14:08:48 +0530624func (PONRMgr *PONResourceManager) GetResourceID(ctx context.Context, IntfID uint32, ResourceType string, NumIDs uint32) ([]uint32, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400625 /*
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
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400638
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400639 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
640 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
npujarec5762e2020-01-01 14:08:48 +0530641 return SharedResourceMgr.GetResourceID(ctx, IntfID, ResourceType, NumIDs)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400642 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400643 log.Debugf("Fetching resource from %s rsrc mgr for resource %s", PONRMgr.Globalorlocal, ResourceType)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400644
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400645 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
npujarec5762e2020-01-01 14:08:48 +0530653 Resource, err := PONRMgr.GetResource(ctx, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400654 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 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400681
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400682 //Update resource in kv store
npujarec5762e2020-01-01 14:08:48 +0530683 if PONRMgr.UpdateResource(ctx, Path, Resource) != nil {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400684 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
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400688}
689
690func checkValidResourceType(ResourceType string) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400691 KnownResourceTypes := []string{ONU_ID, ALLOC_ID, GEMPORT_ID, FLOW_ID}
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400692
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400693 for _, v := range KnownResourceTypes {
694 if v == ResourceType {
695 return true
696 }
697 }
698 return false
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400699}
700
npujarec5762e2020-01-01 14:08:48 +0530701func (PONRMgr *PONResourceManager) FreeResourceID(ctx context.Context, IntfID uint32, ResourceType string, ReleaseContent []uint32) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400702 /*
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 {
npujarec5762e2020-01-01 14:08:48 +0530720 return SharedResourceMgr.FreeResourceID(ctx, IntfID, ResourceType, ReleaseContent)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400721 }
722 Path := PONRMgr.GetPath(IntfID, ResourceType)
723 if Path == "" {
724 log.Error("Failed to get path")
725 return false
726 }
npujarec5762e2020-01-01 14:08:48 +0530727 Resource, err := PONRMgr.GetResource(ctx, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400728 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 }
npujarec5762e2020-01-01 14:08:48 +0530735 if PONRMgr.UpdateResource(ctx, Path, Resource) != nil {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400736 log.Errorf("Free resource for %s failed", Path)
737 return false
738 }
739 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400740}
741
npujarec5762e2020-01-01 14:08:48 +0530742func (PONRMgr *PONResourceManager) UpdateResource(ctx context.Context, Path string, Resource map[string]interface{}) error {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400743 /*
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 }
npujarec5762e2020-01-01 14:08:48 +0530755 err = PONRMgr.KVStore.Put(ctx, Path, Value)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400756 if err != nil {
757 log.Error("failed to put data to kv store %s", Path)
758 return err
759 }
760 return nil
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400761}
762
npujarec5762e2020-01-01 14:08:48 +0530763func (PONRMgr *PONResourceManager) ClearResourceIDPool(ctx context.Context, contIntfID uint32, ResourceType string) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400764 /*
765 Clear Resource Pool for a given Resource Type on a given PON Port.
766 :return boolean: True if removed else False
767 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400768
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400769 // delegate to the master instance if sharing enabled across instances
770 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
771 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
npujarec5762e2020-01-01 14:08:48 +0530772 return SharedResourceMgr.ClearResourceIDPool(ctx, contIntfID, ResourceType)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400773 }
npujarec5762e2020-01-01 14:08:48 +0530774 Path := PONRMgr.GetPath(contIntfID, ResourceType)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400775 if Path == "" {
776 log.Error("Failed to get path")
777 return false
778 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400779
npujarec5762e2020-01-01 14:08:48 +0530780 if err := PONRMgr.KVStore.Delete(ctx, Path); err != nil {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400781 log.Errorf("Failed to delete resource %s", Path)
782 return false
783 }
784 log.Debugf("Cleared resource %s", Path)
785 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400786}
787
npujarec5762e2020-01-01 14:08:48 +0530788func (PONRMgr PONResourceManager) InitResourceMap(ctx context.Context, PONIntfONUID string) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400789 /*
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
npujarec5762e2020-01-01 14:08:48 +0530796 Result := PONRMgr.KVStore.Put(ctx, AllocIDPath, AllocIDs)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400797 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
npujarec5762e2020-01-01 14:08:48 +0530804 Result = PONRMgr.KVStore.Put(ctx, GEMPortIDPath, GEMPortIDs)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400805 if Result != nil {
806 log.Error("Failed to update the KV store")
807 return
808 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400809}
810
npujarec5762e2020-01-01 14:08:48 +0530811func (PONRMgr PONResourceManager) RemoveResourceMap(ctx context.Context, PONIntfONUID string) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400812 /*
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)
npujarec5762e2020-01-01 14:08:48 +0530819 if err = PONRMgr.KVStore.Delete(ctx, AllocIDPath); err != nil {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400820 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)
npujarec5762e2020-01-01 14:08:48 +0530825 err = PONRMgr.KVStore.Delete(ctx, GEMPortIDPath)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400826 if err != nil {
827 log.Errorf("Failed to remove resource %s", GEMPortIDPath)
828 return false
829 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400830
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400831 FlowIDPath := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
npujarec5762e2020-01-01 14:08:48 +0530832 if FlowIDs, err := PONRMgr.KVStore.List(ctx, FlowIDPath); err != nil {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400833 for _, Flow := range FlowIDs {
834 FlowIDInfoPath := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, PONIntfONUID, Flow.Value)
npujarec5762e2020-01-01 14:08:48 +0530835 if err = PONRMgr.KVStore.Delete(ctx, FlowIDInfoPath); err != nil {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400836 log.Errorf("Failed to remove resource %s", FlowIDInfoPath)
837 return false
838 }
839 }
840 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400841
npujarec5762e2020-01-01 14:08:48 +0530842 if err = PONRMgr.KVStore.Delete(ctx, FlowIDPath); err != nil {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400843 log.Errorf("Failed to remove resource %s", FlowIDPath)
844 return false
845 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400846
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400847 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400848}
849
npujarec5762e2020-01-01 14:08:48 +0530850func (PONRMgr *PONResourceManager) GetCurrentAllocIDForOnu(ctx context.Context, IntfONUID string) []uint32 {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400851 /*
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)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400857
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400858 var Data []uint32
npujarec5762e2020-01-01 14:08:48 +0530859 Value, err := PONRMgr.KVStore.Get(ctx, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400860 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
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400874}
875
npujarec5762e2020-01-01 14:08:48 +0530876func (PONRMgr *PONResourceManager) GetCurrentGEMPortIDsForOnu(ctx context.Context, IntfONUID string) []uint32 {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400877 /*
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 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400882
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400883 Path := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
884 log.Debugf("Getting current gemports for %s", Path)
885 var Data []uint32
npujarec5762e2020-01-01 14:08:48 +0530886 Value, err := PONRMgr.KVStore.Get(ctx, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400887 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
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400899}
900
npujarec5762e2020-01-01 14:08:48 +0530901func (PONRMgr *PONResourceManager) GetCurrentFlowIDsForOnu(ctx context.Context, IntfONUID string) []uint32 {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400902 /*
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 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400907
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400908 Path := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400909
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400910 var Data []uint32
npujarec5762e2020-01-01 14:08:48 +0530911 Value, err := PONRMgr.KVStore.Get(ctx, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400912 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
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400922}
923
npujarec5762e2020-01-01 14:08:48 +0530924func (PONRMgr *PONResourceManager) GetFlowIDInfo(ctx context.Context, IntfONUID string, FlowID uint32, Data interface{}) error {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400925 /*
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 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400932
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400933 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400934
npujarec5762e2020-01-01 14:08:48 +0530935 Value, err := PONRMgr.KVStore.Get(ctx, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400936 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
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400950}
951
npujarec5762e2020-01-01 14:08:48 +0530952func (PONRMgr *PONResourceManager) RemoveFlowIDInfo(ctx context.Context, IntfONUID string, FlowID uint32) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400953 /*
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)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400959
npujarec5762e2020-01-01 14:08:48 +0530960 if err := PONRMgr.KVStore.Delete(ctx, Path); err != nil {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400961 log.Errorf("Falied to remove resource %s", Path)
962 return false
963 }
964 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400965}
966
npujarec5762e2020-01-01 14:08:48 +0530967func (PONRMgr *PONResourceManager) UpdateAllocIdsForOnu(ctx context.Context, IntfONUID string, AllocIDs []uint32) error {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400968 /*
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 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400981
npujarec5762e2020-01-01 14:08:48 +0530982 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400983 log.Errorf("Failed to update resource %s", Path)
984 return err
985 }
986 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400987}
988
npujarec5762e2020-01-01 14:08:48 +0530989func (PONRMgr *PONResourceManager) UpdateGEMPortIDsForOnu(ctx context.Context, IntfONUID string, GEMPortIDs []uint32) error {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400990 /*
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 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400995
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400996 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 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001005
npujarec5762e2020-01-01 14:08:48 +05301006 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001007 log.Errorf("Failed to update resource %s", Path)
1008 return err
1009 }
1010 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001011}
1012
1013func checkForFlowIDInList(FlowIDList []uint32, FlowID uint32) (bool, uint32) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001014 /*
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 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001020
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001021 for idx, _ := range FlowIDList {
1022 if FlowID == FlowIDList[idx] {
1023 return true, uint32(idx)
1024 }
1025 }
1026 return false, 0
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001027}
1028
npujarec5762e2020-01-01 14:08:48 +05301029func (PONRMgr *PONResourceManager) UpdateFlowIDForOnu(ctx context.Context, IntfONUID string, FlowID uint32, Add bool) error {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001030 /*
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)
npujarec5762e2020-01-01 14:08:48 +05301042 FlowIDs := PONRMgr.GetCurrentFlowIDsForOnu(ctx, IntfONUID)
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001043
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001044 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 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001061
npujarec5762e2020-01-01 14:08:48 +05301062 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001063 log.Errorf("Failed to update resource %s", Path)
1064 return err
1065 }
1066 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001067}
1068
npujarec5762e2020-01-01 14:08:48 +05301069func (PONRMgr *PONResourceManager) UpdateFlowIDInfoForOnu(ctx context.Context, IntfONUID string, FlowID uint32, FlowData interface{}) error {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001070 /*
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 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001085
npujarec5762e2020-01-01 14:08:48 +05301086 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001087 log.Errorf("Failed to update resource %s", Path)
1088 return err
1089 }
1090 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001091}
1092
1093func (PONRMgr *PONResourceManager) GenerateNextID(Resource map[string]interface{}) (uint32, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001094 /*
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 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001109
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001110 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
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001123}
1124
1125func (PONRMgr *PONResourceManager) ReleaseID(Resource map[string]interface{}, Id uint32) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001126 /*
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)
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001145
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001146 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001147}
1148
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001149func (PONRMgr *PONResourceManager) GetTechnology() string {
1150 return PONRMgr.Technology
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001151}
1152
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001153func (PONRMgr *PONResourceManager) GetResourceTypeAllocID() string {
1154 return ALLOC_ID
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001155}
1156
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001157func (PONRMgr *PONResourceManager) GetResourceTypeGemPortID() string {
1158 return GEMPORT_ID
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001159}
1160
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001161// 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) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001164 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 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001172}
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) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001177 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 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001185}
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001186
npujarec5762e2020-01-01 14:08:48 +05301187func (PONRMgr *PONResourceManager) AddOnuGemInfo(ctx context.Context, intfID uint32, onuGemData interface{}) error {
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001188 /*
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
npujarec5762e2020-01-01 14:08:48 +05301202 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001203 log.Errorf("Failed to update resource %s", Path)
1204 return err
1205 }
1206 return err
1207}
1208
npujarec5762e2020-01-01 14:08:48 +05301209func (PONRMgr *PONResourceManager) GetOnuGemInfo(ctx context.Context, IntfId uint32, onuGemInfo interface{}) error {
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001210 /*
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)
npujarec5762e2020-01-01 14:08:48 +05301218 value, err := PONRMgr.KVStore.Get(ctx, path)
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001219 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
npujarec5762e2020-01-01 14:08:48 +05301239func (PONRMgr *PONResourceManager) DelOnuGemInfoForIntf(ctx context.Context, intfId uint32) error {
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001240 /*
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)
npujarec5762e2020-01-01 14:08:48 +05301246 if err := PONRMgr.KVStore.Delete(ctx, path); err != nil {
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001247 log.Errorf("Falied to remove resource %s", path)
1248 return err
1249 }
1250 return nil
1251}