blob: 2873dbc0b66c506abfe17d6241a2085cd3ac8bf3 [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
Matt Jeanneret384d8c92019-05-06 14:27:31 -040026 bitmap "github.com/boljen/go-bitmap"
27 "github.com/opencord/voltha-go/common/log"
28 tp "github.com/opencord/voltha-go/common/techprofile"
29 "github.com/opencord/voltha-go/db/kvstore"
30 "github.com/opencord/voltha-go/db/model"
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
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400105 //Constants for internal usage.
106 PON_INTF_ID = "pon_intf_id"
107 START_IDX = "start_idx"
108 END_IDX = "end_idx"
109 POOL = "pool"
110 NUM_OF_PON_INTF = 16
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400111
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400112 KVSTORE_RETRY_TIMEOUT = 5
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400113)
114
115//type ResourceTypeIndex string
116//type ResourceType string
117
118type PONResourceManager struct {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400119 //Implements APIs to initialize/allocate/release alloc/gemport/onu IDs.
120 Technology string
121 DeviceType string
122 DeviceID string
123 Backend string // ETCD, or consul
124 Host string // host ip of the KV store
125 Port int // port number for the KV store
126 OLTModel string
127 KVStore *model.Backend
128 TechProfileMgr *tp.TechProfileMgr
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400129
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400130 // Below attribute, pon_resource_ranges, should be initialized
131 // by reading from KV store.
132 PonResourceRanges map[string]interface{}
133 SharedResourceMgrs map[string]*PONResourceManager
134 SharedIdxByType map[string]string
135 IntfIDs []uint32 // list of pon interface IDs
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400136 Globalorlocal string
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400137}
138
139func newKVClient(storeType string, address string, timeout int) (kvstore.Client, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400140 log.Infow("kv-store-type", log.Fields{"store": storeType})
141 switch storeType {
142 case "consul":
143 return kvstore.NewConsulClient(address, timeout)
144 case "etcd":
145 return kvstore.NewEtcdClient(address, timeout)
146 }
147 return nil, errors.New("unsupported-kv-store")
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400148}
149
150func SetKVClient(Technology string, Backend string, Host string, Port int) *model.Backend {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400151 addr := Host + ":" + strconv.Itoa(Port)
152 // TODO : Make sure direct call to NewBackend is working fine with backend , currently there is some
153 // issue between kv store and backend , core is not calling NewBackend directly
154 kvClient, err := newKVClient(Backend, addr, KVSTORE_RETRY_TIMEOUT)
155 if err != nil {
156 log.Fatalw("Failed to init KV client\n", log.Fields{"err": err})
157 return nil
158 }
159 kvbackend := &model.Backend{
160 Client: kvClient,
161 StoreType: Backend,
162 Host: Host,
163 Port: Port,
164 Timeout: KVSTORE_RETRY_TIMEOUT,
165 PathPrefix: fmt.Sprintf(PATH_PREFIX, Technology)}
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400166
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400167 return kvbackend
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400168}
169
170// NewPONResourceManager creates a new PON resource manager.
171func NewPONResourceManager(Technology string, DeviceType string, DeviceID string, Backend string, Host string, Port int) (*PONResourceManager, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400172 var PONMgr PONResourceManager
173 PONMgr.Technology = Technology
174 PONMgr.DeviceType = DeviceType
175 PONMgr.DeviceID = DeviceID
176 PONMgr.Backend = Backend
177 PONMgr.Host = Host
178 PONMgr.Port = Port
179 PONMgr.KVStore = SetKVClient(Technology, Backend, Host, Port)
180 if PONMgr.KVStore == nil {
181 log.Error("KV Client initilization failed")
182 return nil, errors.New("Failed to init KV client")
183 }
184 // Initialize techprofile for this technology
185 if PONMgr.TechProfileMgr, _ = tp.NewTechProfile(&PONMgr); PONMgr.TechProfileMgr == nil {
186 log.Error("Techprofile initialization failed")
187 return nil, errors.New("Failed to init tech profile")
188 }
189 PONMgr.PonResourceRanges = make(map[string]interface{})
190 PONMgr.SharedResourceMgrs = make(map[string]*PONResourceManager)
191 PONMgr.SharedIdxByType = make(map[string]string)
192 PONMgr.SharedIdxByType[ONU_ID] = ONU_ID_SHARED_IDX
193 PONMgr.SharedIdxByType[ALLOC_ID] = ALLOC_ID_SHARED_IDX
194 PONMgr.SharedIdxByType[GEMPORT_ID] = GEMPORT_ID_SHARED_IDX
195 PONMgr.SharedIdxByType[FLOW_ID] = FLOW_ID_SHARED_IDX
196 PONMgr.IntfIDs = make([]uint32, NUM_OF_PON_INTF)
197 PONMgr.OLTModel = DeviceType
198 return &PONMgr, nil
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400199}
200
201/*
202 Initialize PON resource ranges with config fetched from kv store.
203 return boolean: True if PON resource ranges initialized else false
204 Try to initialize the PON Resource Ranges from KV store based on the
205 OLT model key, if available
206*/
207
208func (PONRMgr *PONResourceManager) InitResourceRangesFromKVStore() bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400209 //Initialize PON resource ranges with config fetched from kv store.
210 //:return boolean: True if PON resource ranges initialized else false
211 // Try to initialize the PON Resource Ranges from KV store based on the
212 // OLT model key, if available
213 if PONRMgr.OLTModel == "" {
214 log.Error("Failed to get OLT model")
215 return false
216 }
217 Path := fmt.Sprintf(PON_RESOURCE_RANGE_CONFIG_PATH, PONRMgr.OLTModel)
218 //get resource from kv store
219 Result, err := PONRMgr.KVStore.Get(Path)
220 if err != nil {
221 log.Debugf("Error in fetching resource %s from KV strore", Path)
222 return false
223 }
224 if Result == nil {
225 log.Debug("There may be no resources in the KV store in case of fresh bootup, return true")
226 return false
227 }
228 //update internal ranges from kv ranges. If there are missing
229 // values in the KV profile, continue to use the defaults
230 Value, err := ToByte(Result.Value)
231 if err != nil {
232 log.Error("Failed to convert kvpair to byte string")
233 return false
234 }
235 if err := json.Unmarshal(Value, &PONRMgr.PonResourceRanges); err != nil {
236 log.Error("Failed to Unmarshal json byte")
237 return false
238 }
239 log.Debug("Init resource ranges from kvstore success")
240 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400241}
242
243func (PONRMgr *PONResourceManager) UpdateRanges(StartIDx string, StartID uint32, EndIDx string, EndID uint32,
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400244 SharedIDx string, SharedPoolID uint32, RMgr *PONResourceManager) {
245 /*
246 Update the ranges for all reosurce type in the intermnal maps
247 param: resource type start index
248 param: start ID
249 param: resource type end index
250 param: end ID
251 param: resource type shared index
252 param: shared pool id
253 param: global resource manager
254 */
255 log.Debugf("update ranges for %s, %d", StartIDx, StartID)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400256
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400257 if StartID != 0 {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400258 if (PONRMgr.PonResourceRanges[StartIDx] == nil) || (PONRMgr.PonResourceRanges[StartIDx].(uint32) < StartID) {
259 PONRMgr.PonResourceRanges[StartIDx] = StartID
260 }
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400261 }
262 if EndID != 0 {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400263 if (PONRMgr.PonResourceRanges[EndIDx] == nil) || (PONRMgr.PonResourceRanges[EndIDx].(uint32) > EndID) {
264 PONRMgr.PonResourceRanges[EndIDx] = EndID
265 }
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400266 }
267 //if SharedPoolID != 0 {
268 PONRMgr.PonResourceRanges[SharedIDx] = SharedPoolID
269 //}
270 if RMgr != nil {
271 PONRMgr.SharedResourceMgrs[SharedIDx] = RMgr
272 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400273}
274
275func (PONRMgr *PONResourceManager) InitDefaultPONResourceRanges(ONUIDStart uint32,
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400276 ONUIDEnd uint32,
277 ONUIDSharedPoolID uint32,
278 AllocIDStart uint32,
279 AllocIDEnd uint32,
280 AllocIDSharedPoolID uint32,
281 GEMPortIDStart uint32,
282 GEMPortIDEnd uint32,
283 GEMPortIDSharedPoolID uint32,
284 FlowIDStart uint32,
285 FlowIDEnd uint32,
286 FlowIDSharedPoolID uint32,
287 UNIIDStart uint32,
288 UNIIDEnd uint32,
289 NoOfPONPorts uint32,
290 IntfIDs []uint32) bool {
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400291
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400292 /*Initialize default PON resource ranges
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400293
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400294 :param onu_id_start_idx: onu id start index
295 :param onu_id_end_idx: onu id end index
296 :param onu_id_shared_pool_id: pool idx for id shared by all intfs or None for no sharing
297 :param alloc_id_start_idx: alloc id start index
298 :param alloc_id_end_idx: alloc id end index
299 :param alloc_id_shared_pool_id: pool idx for alloc id shared by all intfs or None for no sharing
300 :param gemport_id_start_idx: gemport id start index
301 :param gemport_id_end_idx: gemport id end index
302 :param gemport_id_shared_pool_id: pool idx for gemport id shared by all intfs or None for no sharing
303 :param flow_id_start_idx: flow id start index
304 :param flow_id_end_idx: flow id end index
305 :param flow_id_shared_pool_id: pool idx for flow id shared by all intfs or None for no sharing
306 :param num_of_pon_ports: number of PON ports
307 :param intf_ids: interfaces serviced by this manager
308 */
309 PONRMgr.UpdateRanges(ONU_ID_START_IDX, ONUIDStart, ONU_ID_END_IDX, ONUIDEnd, ONU_ID_SHARED_IDX, ONUIDSharedPoolID, nil)
310 PONRMgr.UpdateRanges(ALLOC_ID_START_IDX, AllocIDStart, ALLOC_ID_END_IDX, AllocIDEnd, ALLOC_ID_SHARED_IDX, AllocIDSharedPoolID, nil)
311 PONRMgr.UpdateRanges(GEMPORT_ID_START_IDX, GEMPortIDStart, GEMPORT_ID_END_IDX, GEMPortIDEnd, GEMPORT_ID_SHARED_IDX, GEMPortIDSharedPoolID, nil)
312 PONRMgr.UpdateRanges(FLOW_ID_START_IDX, FlowIDStart, FLOW_ID_END_IDX, FlowIDEnd, FLOW_ID_SHARED_IDX, FlowIDSharedPoolID, nil)
313 PONRMgr.UpdateRanges(UNI_ID_START_IDX, UNIIDStart, UNI_ID_END_IDX, UNIIDEnd, "", 0, nil)
314 log.Debug("Initialize default range values")
315 var i uint32
316 if IntfIDs == nil {
317 for i = 0; i < NoOfPONPorts; i++ {
318 PONRMgr.IntfIDs = append(PONRMgr.IntfIDs, i)
319 }
320 } else {
321 PONRMgr.IntfIDs = IntfIDs
322 }
323 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400324}
325
326func (PONRMgr *PONResourceManager) InitDeviceResourcePool() error {
327
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400328 //Initialize resource pool for all PON ports.
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400329
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400330 log.Debug("Init resource ranges")
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400331
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400332 var err error
333 for _, Intf := range PONRMgr.IntfIDs {
334 SharedPoolID := PONRMgr.PonResourceRanges[ONU_ID_SHARED_IDX].(uint32)
335 if SharedPoolID != 0 {
336 Intf = SharedPoolID
337 }
338 if err = PONRMgr.InitResourceIDPool(Intf, ONU_ID,
339 PONRMgr.PonResourceRanges[ONU_ID_START_IDX].(uint32),
340 PONRMgr.PonResourceRanges[ONU_ID_END_IDX].(uint32)); err != nil {
341 log.Error("Failed to init ONU ID resource pool")
342 return err
343 }
344 if SharedPoolID != 0 {
345 break
346 }
347 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400348
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400349 for _, Intf := range PONRMgr.IntfIDs {
350 SharedPoolID := PONRMgr.PonResourceRanges[ALLOC_ID_SHARED_IDX].(uint32)
351 if SharedPoolID != 0 {
352 Intf = SharedPoolID
353 }
354 if err = PONRMgr.InitResourceIDPool(Intf, ALLOC_ID,
355 PONRMgr.PonResourceRanges[ALLOC_ID_START_IDX].(uint32),
356 PONRMgr.PonResourceRanges[ALLOC_ID_END_IDX].(uint32)); err != nil {
357 log.Error("Failed to init ALLOC ID resource pool ")
358 return err
359 }
360 if SharedPoolID != 0 {
361 break
362 }
363 }
364 for _, Intf := range PONRMgr.IntfIDs {
365 SharedPoolID := PONRMgr.PonResourceRanges[GEMPORT_ID_SHARED_IDX].(uint32)
366 if SharedPoolID != 0 {
367 Intf = SharedPoolID
368 }
369 if err = PONRMgr.InitResourceIDPool(Intf, GEMPORT_ID,
370 PONRMgr.PonResourceRanges[GEMPORT_ID_START_IDX].(uint32),
371 PONRMgr.PonResourceRanges[GEMPORT_ID_END_IDX].(uint32)); err != nil {
372 log.Error("Failed to init GEMPORT ID resource pool")
373 return err
374 }
375 if SharedPoolID != 0 {
376 break
377 }
378 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400379
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400380 for _, Intf := range PONRMgr.IntfIDs {
381 SharedPoolID := PONRMgr.PonResourceRanges[FLOW_ID_SHARED_IDX].(uint32)
382 if SharedPoolID != 0 {
383 Intf = SharedPoolID
384 }
385 if err = PONRMgr.InitResourceIDPool(Intf, FLOW_ID,
386 PONRMgr.PonResourceRanges[FLOW_ID_START_IDX].(uint32),
387 PONRMgr.PonResourceRanges[FLOW_ID_END_IDX].(uint32)); err != nil {
388 log.Error("Failed to init FLOW ID resource pool")
389 return err
390 }
391 if SharedPoolID != 0 {
392 break
393 }
394 }
395 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400396}
397
398func (PONRMgr *PONResourceManager) InitResourceIDPool(Intf uint32, ResourceType string, StartID uint32, EndID uint32) error {
399
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400400 /*Initialize Resource ID pool for a given Resource Type on a given PON Port
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400401
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400402 :param pon_intf_id: OLT PON interface id
403 :param resource_type: String to identify type of resource
404 :param start_idx: start index for onu id pool
405 :param end_idx: end index for onu id pool
406 :return boolean: True if resource id pool initialized else false
407 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400408
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400409 // delegate to the master instance if sharing enabled across instances
410 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
411 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
412 return SharedResourceMgr.InitResourceIDPool(Intf, ResourceType, StartID, EndID)
413 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400414
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400415 Path := PONRMgr.GetPath(Intf, ResourceType)
416 if Path == "" {
417 log.Errorf("Failed to get path for resource type %s", ResourceType)
418 return errors.New(fmt.Sprintf("Failed to get path for resource type %s", ResourceType))
419 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400420
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400421 //In case of adapter reboot and reconciliation resource in kv store
422 //checked for its presence if not kv store update happens
423 Res, err := PONRMgr.GetResource(Path)
424 if (err == nil) && (Res != nil) {
425 log.Debugf("Resource %s already present in store ", Path)
426 return nil
427 } else {
428 FormatResult, err := PONRMgr.FormatResource(Intf, StartID, EndID)
429 if err != nil {
430 log.Errorf("Failed to format resource")
431 return err
432 }
433 // Add resource as json in kv store.
434 err = PONRMgr.KVStore.Put(Path, FormatResult)
435 if err == nil {
436 log.Debug("Successfuly posted to kv store")
437 return err
438 }
439 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400440
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400441 log.Debug("Error initializing pool")
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400442
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400443 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400444}
445
446func (PONRMgr *PONResourceManager) FormatResource(IntfID uint32, StartIDx uint32, EndIDx uint32) ([]byte, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400447 /*
448 Format resource as json.
449 :param pon_intf_id: OLT PON interface id
450 :param start_idx: start index for id pool
451 :param end_idx: end index for id pool
452 :return dictionary: resource formatted as map
453 */
454 // Format resource as json to be stored in backend store
455 Resource := make(map[string]interface{})
456 Resource[PON_INTF_ID] = IntfID
457 Resource[START_IDX] = StartIDx
458 Resource[END_IDX] = EndIDx
459 /*
460 Resource pool stored in backend store as binary string.
461 Tracking the resource allocation will be done by setting the bits \
462 in the byte array. The index set will be the resource number allocated.
463 */
464 var TSData *bitmap.Threadsafe
465 if TSData = bitmap.NewTS(int(EndIDx)); TSData == nil {
466 log.Error("Failed to create a bitmap")
467 return nil, errors.New("Failed to create bitmap")
468 }
469 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 -0400470
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400471 Value, err := json.Marshal(Resource)
472 if err != nil {
473 log.Errorf("Failed to marshall resource")
474 return nil, err
475 }
476 return Value, err
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400477}
478func (PONRMgr *PONResourceManager) GetResource(Path string) (map[string]interface{}, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400479 /*
480 Get resource from kv store.
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400481
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400482 :param path: path to get resource
483 :return: resource if resource present in kv store else None
484 */
485 //get resource from kv store
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400486
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400487 var Value []byte
488 Result := make(map[string]interface{})
489 var Str string
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400490
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400491 Resource, err := PONRMgr.KVStore.Get(Path)
492 if (err != nil) || (Resource == nil) {
493 log.Debugf("Resource unavailable at %s", Path)
494 return nil, err
495 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400496
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400497 Value, err = ToByte(Resource.Value)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400498
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400499 // decode resource fetched from backend store to dictionary
500 err = json.Unmarshal(Value, &Result)
501 if err != nil {
502 log.Error("Failed to decode resource")
503 return Result, err
504 }
505 /*
506 resource pool in backend store stored as binary string whereas to
507 access the pool to generate/release IDs it need to be converted
508 as BitArray
509 */
510 Str, err = ToString(Result[POOL])
511 if err != nil {
512 log.Error("Failed to conver to kv pair to string")
513 return Result, err
514 }
515 Decode64, _ := base64.StdEncoding.DecodeString(Str)
516 Result[POOL], err = ToByte(Decode64)
517 if err != nil {
518 log.Error("Failed to convert resource pool to byte")
519 return Result, err
520 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400521
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400522 return Result, err
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400523}
524
525func (PONRMgr *PONResourceManager) GetPath(IntfID uint32, ResourceType string) string {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400526 /*
527 Get path for given resource type.
528 :param pon_intf_id: OLT PON interface id
529 :param resource_type: String to identify type of resource
530 :return: path for given resource type
531 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400532
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400533 /*
534 Get the shared pool for the given resource type.
535 all the resource ranges and the shared resource maps are initialized during the init.
536 */
537 SharedPoolID := PONRMgr.PonResourceRanges[PONRMgr.SharedIdxByType[ResourceType]].(uint32)
538 if SharedPoolID != 0 {
539 IntfID = SharedPoolID
540 }
541 var Path string
542 if ResourceType == ONU_ID {
543 Path = fmt.Sprintf(ONU_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
544 } else if ResourceType == ALLOC_ID {
545 Path = fmt.Sprintf(ALLOC_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
546 } else if ResourceType == GEMPORT_ID {
547 Path = fmt.Sprintf(GEMPORT_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
548 } else if ResourceType == FLOW_ID {
549 Path = fmt.Sprintf(FLOW_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
550 } else {
551 log.Error("Invalid resource pool identifier")
552 }
553 return Path
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400554}
555
556func (PONRMgr *PONResourceManager) GetResourceID(IntfID uint32, ResourceType string, NumIDs uint32) ([]uint32, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400557 /*
558 Create alloc/gemport/onu/flow id for given OLT PON interface.
559 :param pon_intf_id: OLT PON interface id
560 :param resource_type: String to identify type of resource
561 :param num_of_id: required number of ids
562 :return list/uint32/None: list, uint32 or None if resource type is
563 alloc_id/gemport_id, onu_id or invalid type respectively
564 */
565 if NumIDs < 1 {
566 log.Error("Invalid number of resources requested")
567 return nil, errors.New(fmt.Sprintf("Invalid number of resources requested %d", NumIDs))
568 }
569 // delegate to the master instance if sharing enabled across instances
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400570
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400571 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
572 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
573 return SharedResourceMgr.GetResourceID(IntfID, ResourceType, NumIDs)
574 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400575 log.Debugf("Fetching resource from %s rsrc mgr for resource %s", PONRMgr.Globalorlocal, ResourceType)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400576
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400577 Path := PONRMgr.GetPath(IntfID, ResourceType)
578 if Path == "" {
579 log.Errorf("Failed to get path for resource type %s", ResourceType)
580 return nil, errors.New(fmt.Sprintf("Failed to get path for resource type %s", ResourceType))
581 }
582 log.Debugf("Get resource for type %s on path %s", ResourceType, Path)
583 var Result []uint32
584 var NextID uint32
585 Resource, err := PONRMgr.GetResource(Path)
586 if (err == nil) && (ResourceType == ONU_ID) || (ResourceType == FLOW_ID) {
587 if NextID, err = PONRMgr.GenerateNextID(Resource); err != nil {
588 log.Error("Failed to Generate ID")
589 return Result, err
590 }
591 Result = append(Result, NextID)
592 } else if (err == nil) && ((ResourceType == GEMPORT_ID) || (ResourceType == ALLOC_ID)) {
593 if NumIDs == 1 {
594 if NextID, err = PONRMgr.GenerateNextID(Resource); err != nil {
595 log.Error("Failed to Generate ID")
596 return Result, err
597 }
598 Result = append(Result, NextID)
599 } else {
600 for NumIDs > 0 {
601 if NextID, err = PONRMgr.GenerateNextID(Resource); err != nil {
602 log.Error("Failed to Generate ID")
603 return Result, err
604 }
605 Result = append(Result, NextID)
606 NumIDs--
607 }
608 }
609 } else {
610 log.Error("get resource failed")
611 return Result, err
612 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400613
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400614 //Update resource in kv store
615 if PONRMgr.UpdateResource(Path, Resource) != nil {
616 log.Errorf("Failed to update resource %s", Path)
617 return nil, errors.New(fmt.Sprintf("Failed to update resource %s", Path))
618 }
619 return Result, nil
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400620}
621
622func checkValidResourceType(ResourceType string) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400623 KnownResourceTypes := []string{ONU_ID, ALLOC_ID, GEMPORT_ID, FLOW_ID}
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400624
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400625 for _, v := range KnownResourceTypes {
626 if v == ResourceType {
627 return true
628 }
629 }
630 return false
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400631}
632
633func (PONRMgr *PONResourceManager) FreeResourceID(IntfID uint32, ResourceType string, ReleaseContent []uint32) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400634 /*
635 Release alloc/gemport/onu/flow id for given OLT PON interface.
636 :param pon_intf_id: OLT PON interface id
637 :param resource_type: String to identify type of resource
638 :param release_content: required number of ids
639 :return boolean: True if all IDs in given release_content release else False
640 */
641 if checkValidResourceType(ResourceType) == false {
642 log.Error("Invalid resource type")
643 return false
644 }
645 if ReleaseContent == nil {
646 log.Debug("Nothing to release")
647 return true
648 }
649 // delegate to the master instance if sharing enabled across instances
650 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
651 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
652 return SharedResourceMgr.FreeResourceID(IntfID, ResourceType, ReleaseContent)
653 }
654 Path := PONRMgr.GetPath(IntfID, ResourceType)
655 if Path == "" {
656 log.Error("Failed to get path")
657 return false
658 }
659 Resource, err := PONRMgr.GetResource(Path)
660 if err != nil {
661 log.Error("Failed to get resource")
662 return false
663 }
664 for _, Val := range ReleaseContent {
665 PONRMgr.ReleaseID(Resource, Val)
666 }
667 if PONRMgr.UpdateResource(Path, Resource) != nil {
668 log.Errorf("Free resource for %s failed", Path)
669 return false
670 }
671 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400672}
673
674func (PONRMgr *PONResourceManager) UpdateResource(Path string, Resource map[string]interface{}) error {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400675 /*
676 Update resource in resource kv store.
677 :param path: path to update resource
678 :param resource: resource need to be updated
679 :return boolean: True if resource updated in kv store else False
680 */
681 // TODO resource[POOL] = resource[POOL].bin
682 Value, err := json.Marshal(Resource)
683 if err != nil {
684 log.Error("failed to Marshal")
685 return err
686 }
687 err = PONRMgr.KVStore.Put(Path, Value)
688 if err != nil {
689 log.Error("failed to put data to kv store %s", Path)
690 return err
691 }
692 return nil
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400693}
694
695func (PONRMgr *PONResourceManager) ClearResourceIDPool(IntfID uint32, ResourceType string) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400696 /*
697 Clear Resource Pool for a given Resource Type on a given PON Port.
698 :return boolean: True if removed else False
699 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400700
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400701 // delegate to the master instance if sharing enabled across instances
702 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
703 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
704 return SharedResourceMgr.ClearResourceIDPool(IntfID, ResourceType)
705 }
706 Path := PONRMgr.GetPath(IntfID, ResourceType)
707 if Path == "" {
708 log.Error("Failed to get path")
709 return false
710 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400711
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400712 if err := PONRMgr.KVStore.Delete(Path); err != nil {
713 log.Errorf("Failed to delete resource %s", Path)
714 return false
715 }
716 log.Debugf("Cleared resource %s", Path)
717 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400718}
719
720func (PONRMgr PONResourceManager) InitResourceMap(PONIntfONUID string) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400721 /*
722 Initialize resource map
723 :param pon_intf_onu_id: reference of PON interface id and onu id
724 */
725 // initialize pon_intf_onu_id tuple to alloc_ids map
726 AllocIDPath := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
727 var AllocIDs []byte
728 Result := PONRMgr.KVStore.Put(AllocIDPath, AllocIDs)
729 if Result != nil {
730 log.Error("Failed to update the KV store")
731 return
732 }
733 // initialize pon_intf_onu_id tuple to gemport_ids map
734 GEMPortIDPath := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
735 var GEMPortIDs []byte
736 Result = PONRMgr.KVStore.Put(GEMPortIDPath, GEMPortIDs)
737 if Result != nil {
738 log.Error("Failed to update the KV store")
739 return
740 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400741}
742
743func (PONRMgr PONResourceManager) RemoveResourceMap(PONIntfONUID string) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400744 /*
745 Remove resource map
746 :param pon_intf_onu_id: reference of PON interface id and onu id
747 */
748 // remove pon_intf_onu_id tuple to alloc_ids map
749 var err error
750 AllocIDPath := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
751 if err = PONRMgr.KVStore.Delete(AllocIDPath); err != nil {
752 log.Errorf("Failed to remove resource %s", AllocIDPath)
753 return false
754 }
755 // remove pon_intf_onu_id tuple to gemport_ids map
756 GEMPortIDPath := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
757 err = PONRMgr.KVStore.Delete(GEMPortIDPath)
758 if err != nil {
759 log.Errorf("Failed to remove resource %s", GEMPortIDPath)
760 return false
761 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400762
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400763 FlowIDPath := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
764 if FlowIDs, err := PONRMgr.KVStore.List(FlowIDPath); err != nil {
765 for _, Flow := range FlowIDs {
766 FlowIDInfoPath := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, PONIntfONUID, Flow.Value)
767 if err = PONRMgr.KVStore.Delete(FlowIDInfoPath); err != nil {
768 log.Errorf("Failed to remove resource %s", FlowIDInfoPath)
769 return false
770 }
771 }
772 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400773
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400774 if err = PONRMgr.KVStore.Delete(FlowIDPath); err != nil {
775 log.Errorf("Failed to remove resource %s", FlowIDPath)
776 return false
777 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400778
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400779 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400780}
781
782func (PONRMgr *PONResourceManager) GetCurrentAllocIDForOnu(IntfONUID string) []uint32 {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400783 /*
784 Get currently configured alloc ids for given pon_intf_onu_id
785 :param pon_intf_onu_id: reference of PON interface id and onu id
786 :return list: List of alloc_ids if available, else None
787 */
788 Path := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400789
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400790 var Data []uint32
791 Value, err := PONRMgr.KVStore.Get(Path)
792 if err == nil {
793 if Value != nil {
794 Val, err := ToByte(Value.Value)
795 if err != nil {
796 log.Errorw("Failed to convert into byte array", log.Fields{"error": err})
797 return Data
798 }
799 if err = json.Unmarshal(Val, &Data); err != nil {
800 log.Error("Failed to unmarshal", log.Fields{"error": err})
801 return Data
802 }
803 }
804 }
805 return Data
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400806}
807
808func (PONRMgr *PONResourceManager) GetCurrentGEMPortIDsForOnu(IntfONUID string) []uint32 {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400809 /*
810 Get currently configured gemport ids for given pon_intf_onu_id
811 :param pon_intf_onu_id: reference of PON interface id and onu id
812 :return list: List of gemport IDs if available, else None
813 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400814
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400815 Path := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
816 log.Debugf("Getting current gemports for %s", Path)
817 var Data []uint32
818 Value, err := PONRMgr.KVStore.Get(Path)
819 if err == nil {
820 if Value != nil {
821 Val, _ := ToByte(Value.Value)
822 if err = json.Unmarshal(Val, &Data); err != nil {
823 log.Errorw("Failed to unmarshal", log.Fields{"error": err})
824 return Data
825 }
826 }
827 } else {
828 log.Errorf("Failed to get data from kvstore for %s", Path)
829 }
830 return Data
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400831}
832
833func (PONRMgr *PONResourceManager) GetCurrentFlowIDsForOnu(IntfONUID string) []uint32 {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400834 /*
835 Get currently configured flow ids for given pon_intf_onu_id
836 :param pon_intf_onu_id: reference of PON interface id and onu id
837 :return list: List of Flow IDs if available, else None
838 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400839
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400840 Path := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400841
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400842 var Data []uint32
843 Value, err := PONRMgr.KVStore.Get(Path)
844 if err == nil {
845 if Value != nil {
846 Val, _ := ToByte(Value.Value)
847 if err = json.Unmarshal(Val, &Data); err != nil {
848 log.Error("Failed to unmarshal")
849 return Data
850 }
851 }
852 }
853 return Data
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400854}
855
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400856func (PONRMgr *PONResourceManager) GetFlowIDInfo(IntfONUID string, FlowID uint32, Data interface{}) error {
857 /*
858 Get flow details configured for the ONU.
859 :param pon_intf_onu_id: reference of PON interface id and onu id
860 :param flow_id: Flow Id reference
861 :param Data: Result
862 :return error: nil if no error in getting from KV store
863 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400864
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400865 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400866
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400867 Value, err := PONRMgr.KVStore.Get(Path)
868 if err == nil {
869 if Value != nil {
870 Val, err := ToByte(Value.Value)
871 if err != nil {
872 log.Errorw("Failed to convert flowinfo into byte array", log.Fields{"error": err})
873 return err
874 }
875 if err = json.Unmarshal(Val, Data); err != nil {
876 log.Errorw("Failed to unmarshal", log.Fields{"error": err})
877 return err
878 }
879 }
880 }
881 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400882}
883
884func (PONRMgr *PONResourceManager) RemoveFlowIDInfo(IntfONUID string, FlowID uint32) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400885 /*
886 Get flow_id details configured for the ONU.
887 :param pon_intf_onu_id: reference of PON interface id and onu id
888 :param flow_id: Flow Id reference
889 */
890 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400891
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400892 if err := PONRMgr.KVStore.Delete(Path); err != nil {
893 log.Errorf("Falied to remove resource %s", Path)
894 return false
895 }
896 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400897}
898
899func (PONRMgr *PONResourceManager) UpdateAllocIdsForOnu(IntfONUID string, AllocIDs []uint32) error {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400900 /*
901 Update currently configured alloc ids for given pon_intf_onu_id
902 :param pon_intf_onu_id: reference of PON interface id and onu id
903 :param alloc_ids: list of alloc ids
904 */
905 var Value []byte
906 var err error
907 Path := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
908 Value, err = json.Marshal(AllocIDs)
909 if err != nil {
910 log.Error("failed to Marshal")
911 return err
912 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400913
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400914 if err = PONRMgr.KVStore.Put(Path, Value); err != nil {
915 log.Errorf("Failed to update resource %s", Path)
916 return err
917 }
918 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400919}
920
921func (PONRMgr *PONResourceManager) UpdateGEMPortIDsForOnu(IntfONUID string, GEMPortIDs []uint32) error {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400922 /*
923 Update currently configured gemport ids for given pon_intf_onu_id
924 :param pon_intf_onu_id: reference of PON interface id and onu id
925 :param gemport_ids: list of gem port ids
926 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400927
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400928 var Value []byte
929 var err error
930 Path := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
931 log.Debugf("Updating gemport ids for %s", Path)
932 Value, err = json.Marshal(GEMPortIDs)
933 if err != nil {
934 log.Error("failed to Marshal")
935 return err
936 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400937
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400938 if err = PONRMgr.KVStore.Put(Path, Value); err != nil {
939 log.Errorf("Failed to update resource %s", Path)
940 return err
941 }
942 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400943}
944
945func checkForFlowIDInList(FlowIDList []uint32, FlowID uint32) (bool, uint32) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400946 /*
947 Check for a flow id in a given list of flow IDs.
948 :param FLowIDList: List of Flow IDs
949 :param FlowID: Flowd to check in the list
950 : return true and the index if present false otherwise.
951 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400952
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400953 for idx, _ := range FlowIDList {
954 if FlowID == FlowIDList[idx] {
955 return true, uint32(idx)
956 }
957 }
958 return false, 0
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400959}
960
961func (PONRMgr *PONResourceManager) UpdateFlowIDForOnu(IntfONUID string, FlowID uint32, Add bool) error {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400962 /*
963 Update the flow_id list of the ONU (add or remove flow_id from the list)
964 :param pon_intf_onu_id: reference of PON interface id and onu id
965 :param flow_id: flow ID
966 :param add: Boolean flag to indicate whether the flow_id should be
967 added or removed from the list. Defaults to adding the flow.
968 */
969 var Value []byte
970 var err error
971 var RetVal bool
972 var IDx uint32
973 Path := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
974 FlowIDs := PONRMgr.GetCurrentFlowIDsForOnu(IntfONUID)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400975
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400976 if Add {
977 if RetVal, IDx = checkForFlowIDInList(FlowIDs, FlowID); RetVal == true {
978 return err
979 }
980 FlowIDs = append(FlowIDs, FlowID)
981 } else {
982 if RetVal, IDx = checkForFlowIDInList(FlowIDs, FlowID); RetVal == false {
983 return err
984 }
985 // delete the index and shift
986 FlowIDs = append(FlowIDs[:IDx], FlowIDs[IDx+1:]...)
987 }
988 Value, err = json.Marshal(FlowIDs)
989 if err != nil {
990 log.Error("Failed to Marshal")
991 return err
992 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400993
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400994 if err = PONRMgr.KVStore.Put(Path, Value); err != nil {
995 log.Errorf("Failed to update resource %s", Path)
996 return err
997 }
998 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400999}
1000
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001001func (PONRMgr *PONResourceManager) UpdateFlowIDInfoForOnu(IntfONUID string, FlowID uint32, FlowData interface{}) error {
1002 /*
1003 Update any metadata associated with the flow_id. The flow_data could be json
1004 or any of other data structure. The resource manager doesnt care
1005 :param pon_intf_onu_id: reference of PON interface id and onu id
1006 :param flow_id: Flow ID
1007 :param flow_data: Flow data blob
1008 */
1009 var Value []byte
1010 var err error
1011 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
1012 Value, err = json.Marshal(FlowData)
1013 if err != nil {
1014 log.Error("failed to Marshal")
1015 return err
1016 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001017
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001018 if err = PONRMgr.KVStore.Put(Path, Value); err != nil {
1019 log.Errorf("Failed to update resource %s", Path)
1020 return err
1021 }
1022 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001023}
1024
1025func (PONRMgr *PONResourceManager) GenerateNextID(Resource map[string]interface{}) (uint32, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001026 /*
1027 Generate unique id having OFFSET as start
1028 :param resource: resource used to generate ID
1029 :return uint32: generated id
1030 */
1031 ByteArray, err := ToByte(Resource[POOL])
1032 if err != nil {
1033 log.Error("Failed to convert resource to byte array")
1034 return 0, err
1035 }
1036 Data := bitmap.TSFromData(ByteArray, false)
1037 if Data == nil {
1038 log.Error("Failed to get data from byte array")
1039 return 0, errors.New("Failed to get data from byte array")
1040 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001041
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001042 Len := Data.Len()
1043 var Idx int
1044 for Idx = 0; Idx < Len; Idx++ {
1045 Val := Data.Get(Idx)
1046 if Val == false {
1047 break
1048 }
1049 }
1050 Data.Set(Idx, true)
1051 res := uint32(Resource[START_IDX].(float64))
1052 Resource[POOL] = Data.Data(false)
1053 log.Debugf("Generated ID for %d", (uint32(Idx) + res))
1054 return (uint32(Idx) + res), err
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001055}
1056
1057func (PONRMgr *PONResourceManager) ReleaseID(Resource map[string]interface{}, Id uint32) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001058 /*
1059 Release unique id having OFFSET as start index.
1060 :param resource: resource used to release ID
1061 :param unique_id: id need to be released
1062 */
1063 ByteArray, err := ToByte(Resource[POOL])
1064 if err != nil {
1065 log.Error("Failed to convert resource to byte array")
1066 return false
1067 }
1068 Data := bitmap.TSFromData(ByteArray, false)
1069 if Data == nil {
1070 log.Error("Failed to get resource pool")
1071 return false
1072 }
1073 var Idx uint32
1074 Idx = Id - uint32(Resource[START_IDX].(float64))
1075 Data.Set(int(Idx), false)
1076 Resource[POOL] = Data.Data(false)
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001077
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001078 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001079}
1080
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001081func (PONRMgr *PONResourceManager) GetTechnology() string {
1082 return PONRMgr.Technology
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001083}
1084
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001085func (PONRMgr *PONResourceManager) GetResourceTypeAllocID() string {
1086 return ALLOC_ID
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001087}
1088
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001089func (PONRMgr *PONResourceManager) GetResourceTypeGemPortID() string {
1090 return GEMPORT_ID
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001091}
1092
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001093// ToByte converts an interface value to a []byte. The interface should either be of
1094// a string type or []byte. Otherwise, an error is returned.
1095func ToByte(value interface{}) ([]byte, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001096 switch t := value.(type) {
1097 case []byte:
1098 return value.([]byte), nil
1099 case string:
1100 return []byte(value.(string)), nil
1101 default:
1102 return nil, fmt.Errorf("unexpected-type-%T", t)
1103 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001104}
1105
1106// ToString converts an interface value to a string. The interface should either be of
1107// a string type or []byte. Otherwise, an error is returned.
1108func ToString(value interface{}) (string, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001109 switch t := value.(type) {
1110 case []byte:
1111 return string(value.([]byte)), nil
1112 case string:
1113 return value.(string), nil
1114 default:
1115 return "", fmt.Errorf("unexpected-type-%T", t)
1116 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001117}