blob: 0abe6c1078d63926b442dcd90737475d2a48c994 [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 (
Matt Jeanneret384d8c92019-05-06 14:27:31 -040020 "encoding/base64"
21 "encoding/json"
22 "errors"
23 "fmt"
24 "strconv"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040025
sbarbaria8910ba2019-11-05 10:12:23 -050026 "github.com/boljen/go-bitmap"
27 "github.com/opencord/voltha-lib-go/v2/pkg/db"
Scott Baker51290152019-10-24 14:23:20 -070028 "github.com/opencord/voltha-lib-go/v2/pkg/db/kvstore"
Scott Baker51290152019-10-24 14:23:20 -070029 "github.com/opencord/voltha-lib-go/v2/pkg/log"
30 tp "github.com/opencord/voltha-lib-go/v2/pkg/techprofile"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040031)
32
33const (
Matt Jeanneret384d8c92019-05-06 14:27:31 -040034 //Constants to identify resource pool
35 UNI_ID = "UNI_ID"
36 ONU_ID = "ONU_ID"
37 ALLOC_ID = "ALLOC_ID"
38 GEMPORT_ID = "GEMPORT_ID"
39 FLOW_ID = "FLOW_ID"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040040
Matt Jeanneret384d8c92019-05-06 14:27:31 -040041 //Constants for passing command line arugments
42 OLT_MODEL_ARG = "--olt_model"
43 PATH_PREFIX = "service/voltha/resource_manager/{%s}"
44 /*The resource ranges for a given device model should be placed
45 at 'resource_manager/<technology>/resource_ranges/<olt_model_type>'
46 path on the KV store.
47 If Resource Range parameters are to be read from the external KV store,
48 they are expected to be stored in the following format.
49 Note: All parameters are MANDATORY for now.
50 constants used as keys to reference the resource range parameters from
51 and external KV store.
52 */
53 UNI_ID_START_IDX = "uni_id_start"
54 UNI_ID_END_IDX = "uni_id_end"
55 ONU_ID_START_IDX = "onu_id_start"
56 ONU_ID_END_IDX = "onu_id_end"
57 ONU_ID_SHARED_IDX = "onu_id_shared"
58 ALLOC_ID_START_IDX = "alloc_id_start"
59 ALLOC_ID_END_IDX = "alloc_id_end"
60 ALLOC_ID_SHARED_IDX = "alloc_id_shared"
61 GEMPORT_ID_START_IDX = "gemport_id_start"
62 GEMPORT_ID_END_IDX = "gemport_id_end"
63 GEMPORT_ID_SHARED_IDX = "gemport_id_shared"
64 FLOW_ID_START_IDX = "flow_id_start"
65 FLOW_ID_END_IDX = "flow_id_end"
66 FLOW_ID_SHARED_IDX = "flow_id_shared"
67 NUM_OF_PON_PORT = "pon_ports"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040068
Matt Jeanneret384d8c92019-05-06 14:27:31 -040069 /*
70 The KV store backend is initialized with a path prefix and we need to
71 provide only the suffix.
72 */
73 PON_RESOURCE_RANGE_CONFIG_PATH = "resource_ranges/%s"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040074
Matt Jeanneret384d8c92019-05-06 14:27:31 -040075 //resource path suffix
76 //Path on the KV store for storing alloc id ranges and resource pool for a given interface
77 //Format: <device_id>/alloc_id_pool/<pon_intf_id>
78 ALLOC_ID_POOL_PATH = "{%s}/alloc_id_pool/{%d}"
79 //Path on the KV store for storing gemport id ranges and resource pool for a given interface
80 //Format: <device_id>/gemport_id_pool/<pon_intf_id>
81 GEMPORT_ID_POOL_PATH = "{%s}/gemport_id_pool/{%d}"
82 //Path on the KV store for storing onu id ranges and resource pool for a given interface
83 //Format: <device_id>/onu_id_pool/<pon_intf_id>
84 ONU_ID_POOL_PATH = "{%s}/onu_id_pool/{%d}"
85 //Path on the KV store for storing flow id ranges and resource pool for a given interface
86 //Format: <device_id>/flow_id_pool/<pon_intf_id>
87 FLOW_ID_POOL_PATH = "{%s}/flow_id_pool/{%d}"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040088
Matt Jeanneret384d8c92019-05-06 14:27:31 -040089 //Path on the KV store for storing list of alloc IDs for a given ONU
90 //Format: <device_id>/<(pon_intf_id, onu_id)>/alloc_ids
91 ALLOC_ID_RESOURCE_MAP_PATH = "{%s}/{%s}/alloc_ids"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040092
Matt Jeanneret384d8c92019-05-06 14:27:31 -040093 //Path on the KV store for storing list of gemport IDs for a given ONU
94 //Format: <device_id>/<(pon_intf_id, onu_id)>/gemport_ids
95 GEMPORT_ID_RESOURCE_MAP_PATH = "{%s}/{%s}/gemport_ids"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040096
Matt Jeanneret384d8c92019-05-06 14:27:31 -040097 //Path on the KV store for storing list of Flow IDs for a given ONU
98 //Format: <device_id>/<(pon_intf_id, onu_id)>/flow_ids
99 FLOW_ID_RESOURCE_MAP_PATH = "{%s}/{%s}/flow_ids"
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400100
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400101 //Flow Id info: Use to store more metadata associated with the flow_id
102 //Format: <device_id>/<(pon_intf_id, onu_id)>/flow_id_info/<flow_id>
103 FLOW_ID_INFO_PATH = "{%s}/{%s}/flow_id_info/{%d}"
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400104
Scott Bakerc6e54cb2019-11-04 09:31:25 -0800105 //path on the kvstore to store onugem info map
106 //format: <device-id>/onu_gem_info/<intfid>
107 ONU_GEM_INFO_PATH = "{%s}/onu_gem_info/{%d}" // onu_gem/<(intfid)>
108
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400109 //Constants for internal usage.
110 PON_INTF_ID = "pon_intf_id"
111 START_IDX = "start_idx"
112 END_IDX = "end_idx"
113 POOL = "pool"
114 NUM_OF_PON_INTF = 16
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400115
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400116 KVSTORE_RETRY_TIMEOUT = 5
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400117)
118
119//type ResourceTypeIndex string
120//type ResourceType string
121
122type PONResourceManager struct {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400123 //Implements APIs to initialize/allocate/release alloc/gemport/onu IDs.
124 Technology string
125 DeviceType string
126 DeviceID string
127 Backend string // ETCD, or consul
128 Host string // host ip of the KV store
129 Port int // port number for the KV store
130 OLTModel string
sbarbaria8910ba2019-11-05 10:12:23 -0500131 KVStore *db.Backend
kdarapub26b4502019-10-05 03:02:33 +0530132 TechProfileMgr tp.TechProfileIf // create object of *tp.TechProfileMgr
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400133
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400134 // Below attribute, pon_resource_ranges, should be initialized
135 // by reading from KV store.
136 PonResourceRanges map[string]interface{}
137 SharedResourceMgrs map[string]*PONResourceManager
138 SharedIdxByType map[string]string
139 IntfIDs []uint32 // list of pon interface IDs
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400140 Globalorlocal string
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400141}
142
143func newKVClient(storeType string, address string, timeout int) (kvstore.Client, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400144 log.Infow("kv-store-type", log.Fields{"store": storeType})
145 switch storeType {
146 case "consul":
147 return kvstore.NewConsulClient(address, timeout)
148 case "etcd":
149 return kvstore.NewEtcdClient(address, timeout)
150 }
151 return nil, errors.New("unsupported-kv-store")
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400152}
153
sbarbaria8910ba2019-11-05 10:12:23 -0500154func SetKVClient(Technology string, Backend string, Host string, Port int) *db.Backend {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400155 addr := Host + ":" + strconv.Itoa(Port)
156 // TODO : Make sure direct call to NewBackend is working fine with backend , currently there is some
157 // issue between kv store and backend , core is not calling NewBackend directly
158 kvClient, err := newKVClient(Backend, addr, KVSTORE_RETRY_TIMEOUT)
159 if err != nil {
160 log.Fatalw("Failed to init KV client\n", log.Fields{"err": err})
161 return nil
162 }
sbarbaria8910ba2019-11-05 10:12:23 -0500163 kvbackend := &db.Backend{
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400164 Client: kvClient,
165 StoreType: Backend,
166 Host: Host,
167 Port: Port,
168 Timeout: KVSTORE_RETRY_TIMEOUT,
169 PathPrefix: fmt.Sprintf(PATH_PREFIX, Technology)}
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400170
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400171 return kvbackend
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400172}
173
174// NewPONResourceManager creates a new PON resource manager.
175func NewPONResourceManager(Technology string, DeviceType string, DeviceID string, Backend string, Host string, Port int) (*PONResourceManager, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400176 var PONMgr PONResourceManager
177 PONMgr.Technology = Technology
178 PONMgr.DeviceType = DeviceType
179 PONMgr.DeviceID = DeviceID
180 PONMgr.Backend = Backend
181 PONMgr.Host = Host
182 PONMgr.Port = Port
183 PONMgr.KVStore = SetKVClient(Technology, Backend, Host, Port)
184 if PONMgr.KVStore == nil {
185 log.Error("KV Client initilization failed")
186 return nil, errors.New("Failed to init KV client")
187 }
188 // Initialize techprofile for this technology
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400189 if PONMgr.TechProfileMgr, _ = tp.NewTechProfile(&PONMgr, Backend, Host, Port); PONMgr.TechProfileMgr == nil {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400190 log.Error("Techprofile initialization failed")
191 return nil, errors.New("Failed to init tech profile")
192 }
193 PONMgr.PonResourceRanges = make(map[string]interface{})
194 PONMgr.SharedResourceMgrs = make(map[string]*PONResourceManager)
195 PONMgr.SharedIdxByType = make(map[string]string)
196 PONMgr.SharedIdxByType[ONU_ID] = ONU_ID_SHARED_IDX
197 PONMgr.SharedIdxByType[ALLOC_ID] = ALLOC_ID_SHARED_IDX
198 PONMgr.SharedIdxByType[GEMPORT_ID] = GEMPORT_ID_SHARED_IDX
199 PONMgr.SharedIdxByType[FLOW_ID] = FLOW_ID_SHARED_IDX
200 PONMgr.IntfIDs = make([]uint32, NUM_OF_PON_INTF)
201 PONMgr.OLTModel = DeviceType
202 return &PONMgr, nil
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400203}
204
205/*
206 Initialize PON resource ranges with config fetched from kv store.
207 return boolean: True if PON resource ranges initialized else false
208 Try to initialize the PON Resource Ranges from KV store based on the
209 OLT model key, if available
210*/
211
212func (PONRMgr *PONResourceManager) InitResourceRangesFromKVStore() bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400213 //Initialize PON resource ranges with config fetched from kv store.
214 //:return boolean: True if PON resource ranges initialized else false
215 // Try to initialize the PON Resource Ranges from KV store based on the
216 // OLT model key, if available
217 if PONRMgr.OLTModel == "" {
218 log.Error("Failed to get OLT model")
219 return false
220 }
221 Path := fmt.Sprintf(PON_RESOURCE_RANGE_CONFIG_PATH, PONRMgr.OLTModel)
222 //get resource from kv store
223 Result, err := PONRMgr.KVStore.Get(Path)
224 if err != nil {
225 log.Debugf("Error in fetching resource %s from KV strore", Path)
226 return false
227 }
228 if Result == nil {
229 log.Debug("There may be no resources in the KV store in case of fresh bootup, return true")
230 return false
231 }
232 //update internal ranges from kv ranges. If there are missing
233 // values in the KV profile, continue to use the defaults
234 Value, err := ToByte(Result.Value)
235 if err != nil {
236 log.Error("Failed to convert kvpair to byte string")
237 return false
238 }
239 if err := json.Unmarshal(Value, &PONRMgr.PonResourceRanges); err != nil {
240 log.Error("Failed to Unmarshal json byte")
241 return false
242 }
243 log.Debug("Init resource ranges from kvstore success")
244 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400245}
246
247func (PONRMgr *PONResourceManager) UpdateRanges(StartIDx string, StartID uint32, EndIDx string, EndID uint32,
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400248 SharedIDx string, SharedPoolID uint32, RMgr *PONResourceManager) {
249 /*
250 Update the ranges for all reosurce type in the intermnal maps
251 param: resource type start index
252 param: start ID
253 param: resource type end index
254 param: end ID
255 param: resource type shared index
256 param: shared pool id
257 param: global resource manager
258 */
259 log.Debugf("update ranges for %s, %d", StartIDx, StartID)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400260
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400261 if StartID != 0 {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400262 if (PONRMgr.PonResourceRanges[StartIDx] == nil) || (PONRMgr.PonResourceRanges[StartIDx].(uint32) < StartID) {
263 PONRMgr.PonResourceRanges[StartIDx] = StartID
264 }
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400265 }
266 if EndID != 0 {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400267 if (PONRMgr.PonResourceRanges[EndIDx] == nil) || (PONRMgr.PonResourceRanges[EndIDx].(uint32) > EndID) {
268 PONRMgr.PonResourceRanges[EndIDx] = EndID
269 }
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400270 }
271 //if SharedPoolID != 0 {
272 PONRMgr.PonResourceRanges[SharedIDx] = SharedPoolID
273 //}
274 if RMgr != nil {
275 PONRMgr.SharedResourceMgrs[SharedIDx] = RMgr
276 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400277}
278
279func (PONRMgr *PONResourceManager) InitDefaultPONResourceRanges(ONUIDStart uint32,
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400280 ONUIDEnd uint32,
281 ONUIDSharedPoolID uint32,
282 AllocIDStart uint32,
283 AllocIDEnd uint32,
284 AllocIDSharedPoolID uint32,
285 GEMPortIDStart uint32,
286 GEMPortIDEnd uint32,
287 GEMPortIDSharedPoolID uint32,
288 FlowIDStart uint32,
289 FlowIDEnd uint32,
290 FlowIDSharedPoolID uint32,
291 UNIIDStart uint32,
292 UNIIDEnd uint32,
293 NoOfPONPorts uint32,
294 IntfIDs []uint32) bool {
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400295
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400296 /*Initialize default PON resource ranges
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400297
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400298 :param onu_id_start_idx: onu id start index
299 :param onu_id_end_idx: onu id end index
300 :param onu_id_shared_pool_id: pool idx for id shared by all intfs or None for no sharing
301 :param alloc_id_start_idx: alloc id start index
302 :param alloc_id_end_idx: alloc id end index
303 :param alloc_id_shared_pool_id: pool idx for alloc id shared by all intfs or None for no sharing
304 :param gemport_id_start_idx: gemport id start index
305 :param gemport_id_end_idx: gemport id end index
306 :param gemport_id_shared_pool_id: pool idx for gemport id shared by all intfs or None for no sharing
307 :param flow_id_start_idx: flow id start index
308 :param flow_id_end_idx: flow id end index
309 :param flow_id_shared_pool_id: pool idx for flow id shared by all intfs or None for no sharing
310 :param num_of_pon_ports: number of PON ports
311 :param intf_ids: interfaces serviced by this manager
312 */
313 PONRMgr.UpdateRanges(ONU_ID_START_IDX, ONUIDStart, ONU_ID_END_IDX, ONUIDEnd, ONU_ID_SHARED_IDX, ONUIDSharedPoolID, nil)
314 PONRMgr.UpdateRanges(ALLOC_ID_START_IDX, AllocIDStart, ALLOC_ID_END_IDX, AllocIDEnd, ALLOC_ID_SHARED_IDX, AllocIDSharedPoolID, nil)
315 PONRMgr.UpdateRanges(GEMPORT_ID_START_IDX, GEMPortIDStart, GEMPORT_ID_END_IDX, GEMPortIDEnd, GEMPORT_ID_SHARED_IDX, GEMPortIDSharedPoolID, nil)
316 PONRMgr.UpdateRanges(FLOW_ID_START_IDX, FlowIDStart, FLOW_ID_END_IDX, FlowIDEnd, FLOW_ID_SHARED_IDX, FlowIDSharedPoolID, nil)
317 PONRMgr.UpdateRanges(UNI_ID_START_IDX, UNIIDStart, UNI_ID_END_IDX, UNIIDEnd, "", 0, nil)
318 log.Debug("Initialize default range values")
319 var i uint32
320 if IntfIDs == nil {
321 for i = 0; i < NoOfPONPorts; i++ {
322 PONRMgr.IntfIDs = append(PONRMgr.IntfIDs, i)
323 }
324 } else {
325 PONRMgr.IntfIDs = IntfIDs
326 }
327 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400328}
329
330func (PONRMgr *PONResourceManager) InitDeviceResourcePool() error {
331
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400332 //Initialize resource pool for all PON ports.
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400333
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400334 log.Debug("Init resource ranges")
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400335
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400336 var err error
337 for _, Intf := range PONRMgr.IntfIDs {
338 SharedPoolID := PONRMgr.PonResourceRanges[ONU_ID_SHARED_IDX].(uint32)
339 if SharedPoolID != 0 {
340 Intf = SharedPoolID
341 }
342 if err = PONRMgr.InitResourceIDPool(Intf, ONU_ID,
343 PONRMgr.PonResourceRanges[ONU_ID_START_IDX].(uint32),
344 PONRMgr.PonResourceRanges[ONU_ID_END_IDX].(uint32)); err != nil {
345 log.Error("Failed to init ONU ID resource pool")
346 return err
347 }
348 if SharedPoolID != 0 {
349 break
350 }
351 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400352
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400353 for _, Intf := range PONRMgr.IntfIDs {
354 SharedPoolID := PONRMgr.PonResourceRanges[ALLOC_ID_SHARED_IDX].(uint32)
355 if SharedPoolID != 0 {
356 Intf = SharedPoolID
357 }
358 if err = PONRMgr.InitResourceIDPool(Intf, ALLOC_ID,
359 PONRMgr.PonResourceRanges[ALLOC_ID_START_IDX].(uint32),
360 PONRMgr.PonResourceRanges[ALLOC_ID_END_IDX].(uint32)); err != nil {
361 log.Error("Failed to init ALLOC ID resource pool ")
362 return err
363 }
364 if SharedPoolID != 0 {
365 break
366 }
367 }
368 for _, Intf := range PONRMgr.IntfIDs {
369 SharedPoolID := PONRMgr.PonResourceRanges[GEMPORT_ID_SHARED_IDX].(uint32)
370 if SharedPoolID != 0 {
371 Intf = SharedPoolID
372 }
373 if err = PONRMgr.InitResourceIDPool(Intf, GEMPORT_ID,
374 PONRMgr.PonResourceRanges[GEMPORT_ID_START_IDX].(uint32),
375 PONRMgr.PonResourceRanges[GEMPORT_ID_END_IDX].(uint32)); err != nil {
376 log.Error("Failed to init GEMPORT ID resource pool")
377 return err
378 }
379 if SharedPoolID != 0 {
380 break
381 }
382 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400383
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400384 for _, Intf := range PONRMgr.IntfIDs {
385 SharedPoolID := PONRMgr.PonResourceRanges[FLOW_ID_SHARED_IDX].(uint32)
386 if SharedPoolID != 0 {
387 Intf = SharedPoolID
388 }
389 if err = PONRMgr.InitResourceIDPool(Intf, FLOW_ID,
390 PONRMgr.PonResourceRanges[FLOW_ID_START_IDX].(uint32),
391 PONRMgr.PonResourceRanges[FLOW_ID_END_IDX].(uint32)); err != nil {
392 log.Error("Failed to init FLOW ID resource pool")
393 return err
394 }
395 if SharedPoolID != 0 {
396 break
397 }
398 }
399 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400400}
401
Devmalya Paul495b94a2019-08-27 19:42:00 -0400402func (PONRMgr *PONResourceManager) ClearDeviceResourcePool() error {
403
404 //Clear resource pool for all PON ports.
405
406 log.Debug("Clear resource ranges")
407
408 for _, Intf := range PONRMgr.IntfIDs {
409 SharedPoolID := PONRMgr.PonResourceRanges[ONU_ID_SHARED_IDX].(uint32)
410 if SharedPoolID != 0 {
411 Intf = SharedPoolID
412 }
413 if status := PONRMgr.ClearResourceIDPool(Intf, ONU_ID); status != true {
414 log.Error("Failed to clear ONU ID resource pool")
415 return errors.New("Failed to clear ONU ID resource pool")
416 }
417 if SharedPoolID != 0 {
418 break
419 }
420 }
421
422 for _, Intf := range PONRMgr.IntfIDs {
423 SharedPoolID := PONRMgr.PonResourceRanges[ALLOC_ID_SHARED_IDX].(uint32)
424 if SharedPoolID != 0 {
425 Intf = SharedPoolID
426 }
427 if status := PONRMgr.ClearResourceIDPool(Intf, ALLOC_ID); status != true {
428 log.Error("Failed to clear ALLOC ID resource pool ")
429 return errors.New("Failed to clear ALLOC ID resource pool")
430 }
431 if SharedPoolID != 0 {
432 break
433 }
434 }
435 for _, Intf := range PONRMgr.IntfIDs {
436 SharedPoolID := PONRMgr.PonResourceRanges[GEMPORT_ID_SHARED_IDX].(uint32)
437 if SharedPoolID != 0 {
438 Intf = SharedPoolID
439 }
440 if status := PONRMgr.ClearResourceIDPool(Intf, GEMPORT_ID); status != true {
441 log.Error("Failed to clear GEMPORT ID resource pool")
442 return errors.New("Failed to clear GEMPORT ID resource pool")
443 }
444 if SharedPoolID != 0 {
445 break
446 }
447 }
448
449 for _, Intf := range PONRMgr.IntfIDs {
450 SharedPoolID := PONRMgr.PonResourceRanges[FLOW_ID_SHARED_IDX].(uint32)
451 if SharedPoolID != 0 {
452 Intf = SharedPoolID
453 }
454 if status := PONRMgr.ClearResourceIDPool(Intf, FLOW_ID); status != true {
455 log.Error("Failed to clear FLOW ID resource pool")
456 return errors.New("Failed to clear FLOW ID resource pool")
457 }
458 if SharedPoolID != 0 {
459 break
460 }
461 }
462 return nil
463}
464
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400465func (PONRMgr *PONResourceManager) InitResourceIDPool(Intf uint32, ResourceType string, StartID uint32, EndID uint32) error {
466
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400467 /*Initialize Resource ID pool for a given Resource Type on a given PON Port
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400468
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400469 :param pon_intf_id: OLT PON interface id
470 :param resource_type: String to identify type of resource
471 :param start_idx: start index for onu id pool
472 :param end_idx: end index for onu id pool
473 :return boolean: True if resource id pool initialized else false
474 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400475
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400476 // delegate to the master instance if sharing enabled across instances
477 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
478 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
479 return SharedResourceMgr.InitResourceIDPool(Intf, ResourceType, StartID, EndID)
480 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400481
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400482 Path := PONRMgr.GetPath(Intf, ResourceType)
483 if Path == "" {
484 log.Errorf("Failed to get path for resource type %s", ResourceType)
485 return errors.New(fmt.Sprintf("Failed to get path for resource type %s", ResourceType))
486 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400487
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400488 //In case of adapter reboot and reconciliation resource in kv store
489 //checked for its presence if not kv store update happens
490 Res, err := PONRMgr.GetResource(Path)
491 if (err == nil) && (Res != nil) {
492 log.Debugf("Resource %s already present in store ", Path)
493 return nil
494 } else {
495 FormatResult, err := PONRMgr.FormatResource(Intf, StartID, EndID)
496 if err != nil {
497 log.Errorf("Failed to format resource")
498 return err
499 }
500 // Add resource as json in kv store.
501 err = PONRMgr.KVStore.Put(Path, FormatResult)
502 if err == nil {
503 log.Debug("Successfuly posted to kv store")
504 return err
505 }
506 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400507
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400508 log.Debug("Error initializing pool")
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400509
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400510 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400511}
512
513func (PONRMgr *PONResourceManager) FormatResource(IntfID uint32, StartIDx uint32, EndIDx uint32) ([]byte, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400514 /*
515 Format resource as json.
516 :param pon_intf_id: OLT PON interface id
517 :param start_idx: start index for id pool
518 :param end_idx: end index for id pool
519 :return dictionary: resource formatted as map
520 */
521 // Format resource as json to be stored in backend store
522 Resource := make(map[string]interface{})
523 Resource[PON_INTF_ID] = IntfID
524 Resource[START_IDX] = StartIDx
525 Resource[END_IDX] = EndIDx
526 /*
527 Resource pool stored in backend store as binary string.
528 Tracking the resource allocation will be done by setting the bits \
529 in the byte array. The index set will be the resource number allocated.
530 */
531 var TSData *bitmap.Threadsafe
532 if TSData = bitmap.NewTS(int(EndIDx)); TSData == nil {
533 log.Error("Failed to create a bitmap")
534 return nil, errors.New("Failed to create bitmap")
535 }
536 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 -0400537
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400538 Value, err := json.Marshal(Resource)
539 if err != nil {
540 log.Errorf("Failed to marshall resource")
541 return nil, err
542 }
543 return Value, err
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400544}
545func (PONRMgr *PONResourceManager) GetResource(Path string) (map[string]interface{}, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400546 /*
547 Get resource from kv store.
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400548
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400549 :param path: path to get resource
550 :return: resource if resource present in kv store else None
551 */
552 //get resource from kv store
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400553
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400554 var Value []byte
555 Result := make(map[string]interface{})
556 var Str string
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400557
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400558 Resource, err := PONRMgr.KVStore.Get(Path)
559 if (err != nil) || (Resource == nil) {
560 log.Debugf("Resource unavailable at %s", Path)
561 return nil, err
562 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400563
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400564 Value, err = ToByte(Resource.Value)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400565
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400566 // decode resource fetched from backend store to dictionary
567 err = json.Unmarshal(Value, &Result)
568 if err != nil {
569 log.Error("Failed to decode resource")
570 return Result, err
571 }
572 /*
573 resource pool in backend store stored as binary string whereas to
574 access the pool to generate/release IDs it need to be converted
575 as BitArray
576 */
577 Str, err = ToString(Result[POOL])
578 if err != nil {
579 log.Error("Failed to conver to kv pair to string")
580 return Result, err
581 }
582 Decode64, _ := base64.StdEncoding.DecodeString(Str)
583 Result[POOL], err = ToByte(Decode64)
584 if err != nil {
585 log.Error("Failed to convert resource pool to byte")
586 return Result, err
587 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400588
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400589 return Result, err
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400590}
591
592func (PONRMgr *PONResourceManager) GetPath(IntfID uint32, ResourceType string) string {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400593 /*
594 Get path for given resource type.
595 :param pon_intf_id: OLT PON interface id
596 :param resource_type: String to identify type of resource
597 :return: path for given resource type
598 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400599
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400600 /*
601 Get the shared pool for the given resource type.
602 all the resource ranges and the shared resource maps are initialized during the init.
603 */
604 SharedPoolID := PONRMgr.PonResourceRanges[PONRMgr.SharedIdxByType[ResourceType]].(uint32)
605 if SharedPoolID != 0 {
606 IntfID = SharedPoolID
607 }
608 var Path string
609 if ResourceType == ONU_ID {
610 Path = fmt.Sprintf(ONU_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
611 } else if ResourceType == ALLOC_ID {
612 Path = fmt.Sprintf(ALLOC_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
613 } else if ResourceType == GEMPORT_ID {
614 Path = fmt.Sprintf(GEMPORT_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
615 } else if ResourceType == FLOW_ID {
616 Path = fmt.Sprintf(FLOW_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
617 } else {
618 log.Error("Invalid resource pool identifier")
619 }
620 return Path
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400621}
622
623func (PONRMgr *PONResourceManager) GetResourceID(IntfID uint32, ResourceType string, NumIDs uint32) ([]uint32, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400624 /*
625 Create alloc/gemport/onu/flow id for given OLT PON interface.
626 :param pon_intf_id: OLT PON interface id
627 :param resource_type: String to identify type of resource
628 :param num_of_id: required number of ids
629 :return list/uint32/None: list, uint32 or None if resource type is
630 alloc_id/gemport_id, onu_id or invalid type respectively
631 */
632 if NumIDs < 1 {
633 log.Error("Invalid number of resources requested")
634 return nil, errors.New(fmt.Sprintf("Invalid number of resources requested %d", NumIDs))
635 }
636 // delegate to the master instance if sharing enabled across instances
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400637
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400638 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
639 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
640 return SharedResourceMgr.GetResourceID(IntfID, ResourceType, NumIDs)
641 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400642 log.Debugf("Fetching resource from %s rsrc mgr for resource %s", PONRMgr.Globalorlocal, ResourceType)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400643
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400644 Path := PONRMgr.GetPath(IntfID, ResourceType)
645 if Path == "" {
646 log.Errorf("Failed to get path for resource type %s", ResourceType)
647 return nil, errors.New(fmt.Sprintf("Failed to get path for resource type %s", ResourceType))
648 }
649 log.Debugf("Get resource for type %s on path %s", ResourceType, Path)
650 var Result []uint32
651 var NextID uint32
652 Resource, err := PONRMgr.GetResource(Path)
653 if (err == nil) && (ResourceType == ONU_ID) || (ResourceType == FLOW_ID) {
654 if NextID, err = PONRMgr.GenerateNextID(Resource); err != nil {
655 log.Error("Failed to Generate ID")
656 return Result, err
657 }
658 Result = append(Result, NextID)
659 } else if (err == nil) && ((ResourceType == GEMPORT_ID) || (ResourceType == ALLOC_ID)) {
660 if NumIDs == 1 {
661 if NextID, err = PONRMgr.GenerateNextID(Resource); err != nil {
662 log.Error("Failed to Generate ID")
663 return Result, err
664 }
665 Result = append(Result, NextID)
666 } else {
667 for NumIDs > 0 {
668 if NextID, err = PONRMgr.GenerateNextID(Resource); err != nil {
669 log.Error("Failed to Generate ID")
670 return Result, err
671 }
672 Result = append(Result, NextID)
673 NumIDs--
674 }
675 }
676 } else {
677 log.Error("get resource failed")
678 return Result, err
679 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400680
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400681 //Update resource in kv store
682 if PONRMgr.UpdateResource(Path, Resource) != nil {
683 log.Errorf("Failed to update resource %s", Path)
684 return nil, errors.New(fmt.Sprintf("Failed to update resource %s", Path))
685 }
686 return Result, nil
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400687}
688
689func checkValidResourceType(ResourceType string) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400690 KnownResourceTypes := []string{ONU_ID, ALLOC_ID, GEMPORT_ID, FLOW_ID}
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400691
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400692 for _, v := range KnownResourceTypes {
693 if v == ResourceType {
694 return true
695 }
696 }
697 return false
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400698}
699
700func (PONRMgr *PONResourceManager) FreeResourceID(IntfID uint32, ResourceType string, ReleaseContent []uint32) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400701 /*
702 Release alloc/gemport/onu/flow id for given OLT PON interface.
703 :param pon_intf_id: OLT PON interface id
704 :param resource_type: String to identify type of resource
705 :param release_content: required number of ids
706 :return boolean: True if all IDs in given release_content release else False
707 */
708 if checkValidResourceType(ResourceType) == false {
709 log.Error("Invalid resource type")
710 return false
711 }
712 if ReleaseContent == nil {
713 log.Debug("Nothing to release")
714 return true
715 }
716 // delegate to the master instance if sharing enabled across instances
717 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
718 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
719 return SharedResourceMgr.FreeResourceID(IntfID, ResourceType, ReleaseContent)
720 }
721 Path := PONRMgr.GetPath(IntfID, ResourceType)
722 if Path == "" {
723 log.Error("Failed to get path")
724 return false
725 }
726 Resource, err := PONRMgr.GetResource(Path)
727 if err != nil {
728 log.Error("Failed to get resource")
729 return false
730 }
731 for _, Val := range ReleaseContent {
732 PONRMgr.ReleaseID(Resource, Val)
733 }
734 if PONRMgr.UpdateResource(Path, Resource) != nil {
735 log.Errorf("Free resource for %s failed", Path)
736 return false
737 }
738 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400739}
740
741func (PONRMgr *PONResourceManager) UpdateResource(Path string, Resource map[string]interface{}) error {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400742 /*
743 Update resource in resource kv store.
744 :param path: path to update resource
745 :param resource: resource need to be updated
746 :return boolean: True if resource updated in kv store else False
747 */
748 // TODO resource[POOL] = resource[POOL].bin
749 Value, err := json.Marshal(Resource)
750 if err != nil {
751 log.Error("failed to Marshal")
752 return err
753 }
754 err = PONRMgr.KVStore.Put(Path, Value)
755 if err != nil {
756 log.Error("failed to put data to kv store %s", Path)
757 return err
758 }
759 return nil
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400760}
761
762func (PONRMgr *PONResourceManager) ClearResourceIDPool(IntfID uint32, ResourceType string) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400763 /*
764 Clear Resource Pool for a given Resource Type on a given PON Port.
765 :return boolean: True if removed else False
766 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400767
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400768 // delegate to the master instance if sharing enabled across instances
769 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
770 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
771 return SharedResourceMgr.ClearResourceIDPool(IntfID, ResourceType)
772 }
773 Path := PONRMgr.GetPath(IntfID, ResourceType)
774 if Path == "" {
775 log.Error("Failed to get path")
776 return false
777 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400778
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400779 if err := PONRMgr.KVStore.Delete(Path); err != nil {
780 log.Errorf("Failed to delete resource %s", Path)
781 return false
782 }
783 log.Debugf("Cleared resource %s", Path)
784 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400785}
786
787func (PONRMgr PONResourceManager) InitResourceMap(PONIntfONUID string) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400788 /*
789 Initialize resource map
790 :param pon_intf_onu_id: reference of PON interface id and onu id
791 */
792 // initialize pon_intf_onu_id tuple to alloc_ids map
793 AllocIDPath := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
794 var AllocIDs []byte
795 Result := PONRMgr.KVStore.Put(AllocIDPath, AllocIDs)
796 if Result != nil {
797 log.Error("Failed to update the KV store")
798 return
799 }
800 // initialize pon_intf_onu_id tuple to gemport_ids map
801 GEMPortIDPath := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
802 var GEMPortIDs []byte
803 Result = PONRMgr.KVStore.Put(GEMPortIDPath, GEMPortIDs)
804 if Result != nil {
805 log.Error("Failed to update the KV store")
806 return
807 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400808}
809
810func (PONRMgr PONResourceManager) RemoveResourceMap(PONIntfONUID string) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400811 /*
812 Remove resource map
813 :param pon_intf_onu_id: reference of PON interface id and onu id
814 */
815 // remove pon_intf_onu_id tuple to alloc_ids map
816 var err error
817 AllocIDPath := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
818 if err = PONRMgr.KVStore.Delete(AllocIDPath); err != nil {
819 log.Errorf("Failed to remove resource %s", AllocIDPath)
820 return false
821 }
822 // remove pon_intf_onu_id tuple to gemport_ids map
823 GEMPortIDPath := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
824 err = PONRMgr.KVStore.Delete(GEMPortIDPath)
825 if err != nil {
826 log.Errorf("Failed to remove resource %s", GEMPortIDPath)
827 return false
828 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400829
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400830 FlowIDPath := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
831 if FlowIDs, err := PONRMgr.KVStore.List(FlowIDPath); err != nil {
832 for _, Flow := range FlowIDs {
833 FlowIDInfoPath := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, PONIntfONUID, Flow.Value)
834 if err = PONRMgr.KVStore.Delete(FlowIDInfoPath); err != nil {
835 log.Errorf("Failed to remove resource %s", FlowIDInfoPath)
836 return false
837 }
838 }
839 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400840
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400841 if err = PONRMgr.KVStore.Delete(FlowIDPath); err != nil {
842 log.Errorf("Failed to remove resource %s", FlowIDPath)
843 return false
844 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400845
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400846 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400847}
848
849func (PONRMgr *PONResourceManager) GetCurrentAllocIDForOnu(IntfONUID string) []uint32 {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400850 /*
851 Get currently configured alloc ids for given pon_intf_onu_id
852 :param pon_intf_onu_id: reference of PON interface id and onu id
853 :return list: List of alloc_ids if available, else None
854 */
855 Path := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400856
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400857 var Data []uint32
858 Value, err := PONRMgr.KVStore.Get(Path)
859 if err == nil {
860 if Value != nil {
861 Val, err := ToByte(Value.Value)
862 if err != nil {
863 log.Errorw("Failed to convert into byte array", log.Fields{"error": err})
864 return Data
865 }
866 if err = json.Unmarshal(Val, &Data); err != nil {
867 log.Error("Failed to unmarshal", log.Fields{"error": err})
868 return Data
869 }
870 }
871 }
872 return Data
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400873}
874
875func (PONRMgr *PONResourceManager) GetCurrentGEMPortIDsForOnu(IntfONUID string) []uint32 {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400876 /*
877 Get currently configured gemport ids for given pon_intf_onu_id
878 :param pon_intf_onu_id: reference of PON interface id and onu id
879 :return list: List of gemport IDs if available, else None
880 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400881
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400882 Path := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
883 log.Debugf("Getting current gemports for %s", Path)
884 var Data []uint32
885 Value, err := PONRMgr.KVStore.Get(Path)
886 if err == nil {
887 if Value != nil {
888 Val, _ := ToByte(Value.Value)
889 if err = json.Unmarshal(Val, &Data); err != nil {
890 log.Errorw("Failed to unmarshal", log.Fields{"error": err})
891 return Data
892 }
893 }
894 } else {
895 log.Errorf("Failed to get data from kvstore for %s", Path)
896 }
897 return Data
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400898}
899
900func (PONRMgr *PONResourceManager) GetCurrentFlowIDsForOnu(IntfONUID string) []uint32 {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400901 /*
902 Get currently configured flow ids for given pon_intf_onu_id
903 :param pon_intf_onu_id: reference of PON interface id and onu id
904 :return list: List of Flow IDs if available, else None
905 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400906
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400907 Path := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400908
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400909 var Data []uint32
910 Value, err := PONRMgr.KVStore.Get(Path)
911 if err == nil {
912 if Value != nil {
913 Val, _ := ToByte(Value.Value)
914 if err = json.Unmarshal(Val, &Data); err != nil {
915 log.Error("Failed to unmarshal")
916 return Data
917 }
918 }
919 }
920 return Data
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400921}
922
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400923func (PONRMgr *PONResourceManager) GetFlowIDInfo(IntfONUID string, FlowID uint32, Data interface{}) error {
924 /*
925 Get flow details configured for the ONU.
926 :param pon_intf_onu_id: reference of PON interface id and onu id
927 :param flow_id: Flow Id reference
928 :param Data: Result
929 :return error: nil if no error in getting from KV store
930 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400931
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400932 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400933
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400934 Value, err := PONRMgr.KVStore.Get(Path)
935 if err == nil {
936 if Value != nil {
937 Val, err := ToByte(Value.Value)
938 if err != nil {
939 log.Errorw("Failed to convert flowinfo into byte array", log.Fields{"error": err})
940 return err
941 }
942 if err = json.Unmarshal(Val, Data); err != nil {
943 log.Errorw("Failed to unmarshal", log.Fields{"error": err})
944 return err
945 }
946 }
947 }
948 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400949}
950
951func (PONRMgr *PONResourceManager) RemoveFlowIDInfo(IntfONUID string, FlowID uint32) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400952 /*
953 Get flow_id details configured for the ONU.
954 :param pon_intf_onu_id: reference of PON interface id and onu id
955 :param flow_id: Flow Id reference
956 */
957 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400958
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400959 if err := PONRMgr.KVStore.Delete(Path); err != nil {
960 log.Errorf("Falied to remove resource %s", Path)
961 return false
962 }
963 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400964}
965
966func (PONRMgr *PONResourceManager) UpdateAllocIdsForOnu(IntfONUID string, AllocIDs []uint32) error {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400967 /*
968 Update currently configured alloc ids for given pon_intf_onu_id
969 :param pon_intf_onu_id: reference of PON interface id and onu id
970 :param alloc_ids: list of alloc ids
971 */
972 var Value []byte
973 var err error
974 Path := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
975 Value, err = json.Marshal(AllocIDs)
976 if err != nil {
977 log.Error("failed to Marshal")
978 return err
979 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400980
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400981 if err = PONRMgr.KVStore.Put(Path, Value); err != nil {
982 log.Errorf("Failed to update resource %s", Path)
983 return err
984 }
985 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400986}
987
988func (PONRMgr *PONResourceManager) UpdateGEMPortIDsForOnu(IntfONUID string, GEMPortIDs []uint32) error {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400989 /*
990 Update currently configured gemport ids for given pon_intf_onu_id
991 :param pon_intf_onu_id: reference of PON interface id and onu id
992 :param gemport_ids: list of gem port ids
993 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400994
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400995 var Value []byte
996 var err error
997 Path := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
998 log.Debugf("Updating gemport ids for %s", Path)
999 Value, err = json.Marshal(GEMPortIDs)
1000 if err != nil {
1001 log.Error("failed to Marshal")
1002 return err
1003 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001004
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001005 if err = PONRMgr.KVStore.Put(Path, Value); err != nil {
1006 log.Errorf("Failed to update resource %s", Path)
1007 return err
1008 }
1009 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001010}
1011
1012func checkForFlowIDInList(FlowIDList []uint32, FlowID uint32) (bool, uint32) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001013 /*
1014 Check for a flow id in a given list of flow IDs.
1015 :param FLowIDList: List of Flow IDs
1016 :param FlowID: Flowd to check in the list
1017 : return true and the index if present false otherwise.
1018 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001019
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001020 for idx, _ := range FlowIDList {
1021 if FlowID == FlowIDList[idx] {
1022 return true, uint32(idx)
1023 }
1024 }
1025 return false, 0
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001026}
1027
1028func (PONRMgr *PONResourceManager) UpdateFlowIDForOnu(IntfONUID string, FlowID uint32, Add bool) error {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001029 /*
1030 Update the flow_id list of the ONU (add or remove flow_id from the list)
1031 :param pon_intf_onu_id: reference of PON interface id and onu id
1032 :param flow_id: flow ID
1033 :param add: Boolean flag to indicate whether the flow_id should be
1034 added or removed from the list. Defaults to adding the flow.
1035 */
1036 var Value []byte
1037 var err error
1038 var RetVal bool
1039 var IDx uint32
1040 Path := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
1041 FlowIDs := PONRMgr.GetCurrentFlowIDsForOnu(IntfONUID)
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001042
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001043 if Add {
1044 if RetVal, IDx = checkForFlowIDInList(FlowIDs, FlowID); RetVal == true {
1045 return err
1046 }
1047 FlowIDs = append(FlowIDs, FlowID)
1048 } else {
1049 if RetVal, IDx = checkForFlowIDInList(FlowIDs, FlowID); RetVal == false {
1050 return err
1051 }
1052 // delete the index and shift
1053 FlowIDs = append(FlowIDs[:IDx], FlowIDs[IDx+1:]...)
1054 }
1055 Value, err = json.Marshal(FlowIDs)
1056 if err != nil {
1057 log.Error("Failed to Marshal")
1058 return err
1059 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001060
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001061 if err = PONRMgr.KVStore.Put(Path, Value); err != nil {
1062 log.Errorf("Failed to update resource %s", Path)
1063 return err
1064 }
1065 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001066}
1067
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001068func (PONRMgr *PONResourceManager) UpdateFlowIDInfoForOnu(IntfONUID string, FlowID uint32, FlowData interface{}) error {
1069 /*
1070 Update any metadata associated with the flow_id. The flow_data could be json
1071 or any of other data structure. The resource manager doesnt care
1072 :param pon_intf_onu_id: reference of PON interface id and onu id
1073 :param flow_id: Flow ID
1074 :param flow_data: Flow data blob
1075 */
1076 var Value []byte
1077 var err error
1078 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
1079 Value, err = json.Marshal(FlowData)
1080 if err != nil {
1081 log.Error("failed to Marshal")
1082 return err
1083 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001084
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001085 if err = PONRMgr.KVStore.Put(Path, Value); err != nil {
1086 log.Errorf("Failed to update resource %s", Path)
1087 return err
1088 }
1089 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001090}
1091
1092func (PONRMgr *PONResourceManager) GenerateNextID(Resource map[string]interface{}) (uint32, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001093 /*
1094 Generate unique id having OFFSET as start
1095 :param resource: resource used to generate ID
1096 :return uint32: generated id
1097 */
1098 ByteArray, err := ToByte(Resource[POOL])
1099 if err != nil {
1100 log.Error("Failed to convert resource to byte array")
1101 return 0, err
1102 }
1103 Data := bitmap.TSFromData(ByteArray, false)
1104 if Data == nil {
1105 log.Error("Failed to get data from byte array")
1106 return 0, errors.New("Failed to get data from byte array")
1107 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001108
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001109 Len := Data.Len()
1110 var Idx int
1111 for Idx = 0; Idx < Len; Idx++ {
1112 Val := Data.Get(Idx)
1113 if Val == false {
1114 break
1115 }
1116 }
1117 Data.Set(Idx, true)
1118 res := uint32(Resource[START_IDX].(float64))
1119 Resource[POOL] = Data.Data(false)
1120 log.Debugf("Generated ID for %d", (uint32(Idx) + res))
1121 return (uint32(Idx) + res), err
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001122}
1123
1124func (PONRMgr *PONResourceManager) ReleaseID(Resource map[string]interface{}, Id uint32) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001125 /*
1126 Release unique id having OFFSET as start index.
1127 :param resource: resource used to release ID
1128 :param unique_id: id need to be released
1129 */
1130 ByteArray, err := ToByte(Resource[POOL])
1131 if err != nil {
1132 log.Error("Failed to convert resource to byte array")
1133 return false
1134 }
1135 Data := bitmap.TSFromData(ByteArray, false)
1136 if Data == nil {
1137 log.Error("Failed to get resource pool")
1138 return false
1139 }
1140 var Idx uint32
1141 Idx = Id - uint32(Resource[START_IDX].(float64))
1142 Data.Set(int(Idx), false)
1143 Resource[POOL] = Data.Data(false)
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001144
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001145 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001146}
1147
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001148func (PONRMgr *PONResourceManager) GetTechnology() string {
1149 return PONRMgr.Technology
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001150}
1151
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001152func (PONRMgr *PONResourceManager) GetResourceTypeAllocID() string {
1153 return ALLOC_ID
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001154}
1155
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001156func (PONRMgr *PONResourceManager) GetResourceTypeGemPortID() string {
1157 return GEMPORT_ID
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001158}
1159
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001160// ToByte converts an interface value to a []byte. The interface should either be of
1161// a string type or []byte. Otherwise, an error is returned.
1162func ToByte(value interface{}) ([]byte, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001163 switch t := value.(type) {
1164 case []byte:
1165 return value.([]byte), nil
1166 case string:
1167 return []byte(value.(string)), nil
1168 default:
1169 return nil, fmt.Errorf("unexpected-type-%T", t)
1170 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001171}
1172
1173// ToString converts an interface value to a string. The interface should either be of
1174// a string type or []byte. Otherwise, an error is returned.
1175func ToString(value interface{}) (string, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001176 switch t := value.(type) {
1177 case []byte:
1178 return string(value.([]byte)), nil
1179 case string:
1180 return value.(string), nil
1181 default:
1182 return "", fmt.Errorf("unexpected-type-%T", t)
1183 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001184}
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001185
1186func (PONRMgr *PONResourceManager) AddOnuGemInfo(intfID uint32, onuGemData interface{}) error {
1187 /*
1188 Update onugem info map,
1189 :param pon_intf_id: reference of PON interface id
1190 :param onuegmdata: onugem info map
1191 */
1192 var Value []byte
1193 var err error
1194 Path := fmt.Sprintf(ONU_GEM_INFO_PATH, PONRMgr.DeviceID, intfID)
1195 Value, err = json.Marshal(onuGemData)
1196 if err != nil {
1197 log.Error("failed to Marshal")
1198 return err
1199 }
1200
1201 if err = PONRMgr.KVStore.Put(Path, Value); err != nil {
1202 log.Errorf("Failed to update resource %s", Path)
1203 return err
1204 }
1205 return err
1206}
1207
1208func (PONRMgr *PONResourceManager) GetOnuGemInfo(IntfId uint32, onuGemInfo interface{}) error {
1209 /*
1210 Get onugeminfo map from kvstore
1211 :param intfid: refremce pon intfid
1212 :param onuGemInfo: onugem info to return from kv strore.
1213 */
1214 var Val []byte
1215
1216 path := fmt.Sprintf(ONU_GEM_INFO_PATH, PONRMgr.DeviceID, IntfId)
1217 value, err := PONRMgr.KVStore.Get(path)
1218 if err != nil {
1219 log.Errorw("Failed to get from kv store", log.Fields{"path": path})
1220 return err
1221 } else if value == nil {
1222 log.Debug("No onuinfo for path", log.Fields{"path": path})
1223 return nil // returning nil as this could happen if there are no onus for the interface yet
1224 }
1225 if Val, err = kvstore.ToByte(value.Value); err != nil {
1226 log.Error("Failed to convert to byte array")
1227 return err
1228 }
1229
1230 if err = json.Unmarshal(Val, &onuGemInfo); err != nil {
1231 log.Error("Failed to unmarshall")
1232 return err
1233 }
1234 log.Debugw("found onuinfo from path", log.Fields{"path": path, "onuinfo": onuGemInfo})
1235 return err
1236}
1237
1238func (PONRMgr *PONResourceManager) DelOnuGemInfoForIntf(intfId uint32) error {
1239 /*
1240 delete onugem info for an interface from kvstore
1241 :param intfid: refremce pon intfid
1242 */
1243
1244 path := fmt.Sprintf(ONU_GEM_INFO_PATH, PONRMgr.DeviceID, intfId)
1245 if err := PONRMgr.KVStore.Delete(path); err != nil {
1246 log.Errorf("Falied to remove resource %s", path)
1247 return err
1248 }
1249 return nil
1250}