blob: b4f9130cd8c3c9f8d14a7aca49f825d70be4546b [file] [log] [blame]
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +05301/*
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 (
Kent Hagerman0ab4cb22019-04-24 13:13:35 -040020 "encoding/base64"
21 "encoding/json"
22 "errors"
23 "fmt"
24 "strconv"
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +053025
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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"
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +053031)
32
33const (
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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"
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +053040
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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"
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +053068
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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"
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +053074
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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}"
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +053088
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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"
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +053092
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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"
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +053096
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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"
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530100
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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}"
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530104
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530111
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400112 KVSTORE_RETRY_TIMEOUT = 5
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530113)
114
115//type ResourceTypeIndex string
116//type ResourceType string
117
118type PONResourceManager struct {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530129
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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 k6c9689d2019-05-09 12:59:52 -0400136 Globalorlocal string
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530137}
138
139func newKVClient(storeType string, address string, timeout int) (kvstore.Client, error) {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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")
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530148}
149
150func SetKVClient(Technology string, Backend string, Host string, Port int) *model.Backend {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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)}
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530166
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400167 return kvbackend
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530168}
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) {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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
manikkaraj k53de5502019-05-12 05:11:53 -0400185 if PONMgr.TechProfileMgr, _ = tp.NewTechProfile(&PONMgr, Backend, Host, Port); PONMgr.TechProfileMgr == nil {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400186 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
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530199}
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 {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530241}
242
243func (PONRMgr *PONResourceManager) UpdateRanges(StartIDx string, StartID uint32, EndIDx string, EndID uint32,
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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)
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530256
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400257 if StartID != 0 {
manikkaraj k6c9689d2019-05-09 12:59:52 -0400258 if (PONRMgr.PonResourceRanges[StartIDx] == nil) || (PONRMgr.PonResourceRanges[StartIDx].(uint32) < StartID) {
259 PONRMgr.PonResourceRanges[StartIDx] = StartID
260 }
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400261 }
262 if EndID != 0 {
manikkaraj k6c9689d2019-05-09 12:59:52 -0400263 if (PONRMgr.PonResourceRanges[EndIDx] == nil) || (PONRMgr.PonResourceRanges[EndIDx].(uint32) > EndID) {
264 PONRMgr.PonResourceRanges[EndIDx] = EndID
265 }
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400266 }
267 //if SharedPoolID != 0 {
268 PONRMgr.PonResourceRanges[SharedIDx] = SharedPoolID
269 //}
270 if RMgr != nil {
271 PONRMgr.SharedResourceMgrs[SharedIDx] = RMgr
272 }
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530273}
274
275func (PONRMgr *PONResourceManager) InitDefaultPONResourceRanges(ONUIDStart uint32,
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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 {
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530291
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400292 /*Initialize default PON resource ranges
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530293
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530324}
325
326func (PONRMgr *PONResourceManager) InitDeviceResourcePool() error {
327
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400328 //Initialize resource pool for all PON ports.
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530329
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400330 log.Debug("Init resource ranges")
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530331
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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 }
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530348
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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 }
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530379
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530396}
397
398func (PONRMgr *PONResourceManager) InitResourceIDPool(Intf uint32, ResourceType string, StartID uint32, EndID uint32) error {
399
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400400 /*Initialize Resource ID pool for a given Resource Type on a given PON Port
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530401
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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 */
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530408
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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 }
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530414
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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 }
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530420
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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 }
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530440
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400441 log.Debug("Error initializing pool")
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530442
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400443 return err
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530444}
445
446func (PONRMgr *PONResourceManager) FormatResource(IntfID uint32, StartIDx uint32, EndIDx uint32) ([]byte, error) {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530470
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530477}
478func (PONRMgr *PONResourceManager) GetResource(Path string) (map[string]interface{}, error) {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400479 /*
480 Get resource from kv store.
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530481
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530486
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400487 var Value []byte
488 Result := make(map[string]interface{})
489 var Str string
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530490
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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 }
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530496
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400497 Value, err = ToByte(Resource.Value)
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530498
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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 }
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530521
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400522 return Result, err
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530523}
524
525func (PONRMgr *PONResourceManager) GetPath(IntfID uint32, ResourceType string) string {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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 */
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530532
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530554}
555
556func (PONRMgr *PONResourceManager) GetResourceID(IntfID uint32, ResourceType string, NumIDs uint32) ([]uint32, error) {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530570
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400571 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
572 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
573 return SharedResourceMgr.GetResourceID(IntfID, ResourceType, NumIDs)
574 }
manikkaraj k6c9689d2019-05-09 12:59:52 -0400575 log.Debugf("Fetching resource from %s rsrc mgr for resource %s", PONRMgr.Globalorlocal, ResourceType)
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530576
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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 }
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530613
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530620}
621
622func checkValidResourceType(ResourceType string) bool {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400623 KnownResourceTypes := []string{ONU_ID, ALLOC_ID, GEMPORT_ID, FLOW_ID}
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530624
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400625 for _, v := range KnownResourceTypes {
626 if v == ResourceType {
627 return true
628 }
629 }
630 return false
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530631}
632
633func (PONRMgr *PONResourceManager) FreeResourceID(IntfID uint32, ResourceType string, ReleaseContent []uint32) bool {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530672}
673
674func (PONRMgr *PONResourceManager) UpdateResource(Path string, Resource map[string]interface{}) error {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530693}
694
695func (PONRMgr *PONResourceManager) ClearResourceIDPool(IntfID uint32, ResourceType string) bool {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400696 /*
697 Clear Resource Pool for a given Resource Type on a given PON Port.
698 :return boolean: True if removed else False
699 */
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530700
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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 }
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530711
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530718}
719
720func (PONRMgr PONResourceManager) InitResourceMap(PONIntfONUID string) {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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 }
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530741}
742
743func (PONRMgr PONResourceManager) RemoveResourceMap(PONIntfONUID string) bool {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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 }
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530762
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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 }
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530773
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400774 if err = PONRMgr.KVStore.Delete(FlowIDPath); err != nil {
775 log.Errorf("Failed to remove resource %s", FlowIDPath)
776 return false
777 }
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530778
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400779 return true
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530780}
781
782func (PONRMgr *PONResourceManager) GetCurrentAllocIDForOnu(IntfONUID string) []uint32 {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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)
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530789
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530806}
807
808func (PONRMgr *PONResourceManager) GetCurrentGEMPortIDsForOnu(IntfONUID string) []uint32 {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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 */
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530814
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530831}
832
833func (PONRMgr *PONResourceManager) GetCurrentFlowIDsForOnu(IntfONUID string) []uint32 {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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 */
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530839
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400840 Path := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530841
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530854}
855
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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 */
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530864
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400865 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530866
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530882}
883
884func (PONRMgr *PONResourceManager) RemoveFlowIDInfo(IntfONUID string, FlowID uint32) bool {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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)
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530891
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530897}
898
899func (PONRMgr *PONResourceManager) UpdateAllocIdsForOnu(IntfONUID string, AllocIDs []uint32) error {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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 }
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530913
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530919}
920
921func (PONRMgr *PONResourceManager) UpdateGEMPortIDsForOnu(IntfONUID string, GEMPortIDs []uint32) error {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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 */
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530927
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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 }
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530937
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530943}
944
945func checkForFlowIDInList(FlowIDList []uint32, FlowID uint32) (bool, uint32) {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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 */
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530952
Kent Hagerman0ab4cb22019-04-24 13:13:35 -0400953 for idx, _ := range FlowIDList {
954 if FlowID == FlowIDList[idx] {
955 return true, uint32(idx)
956 }
957 }
958 return false, 0
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530959}
960
961func (PONRMgr *PONResourceManager) UpdateFlowIDForOnu(IntfONUID string, FlowID uint32, Add bool) error {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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)
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530975
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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 }
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530993
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +0530999}
1000
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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 }
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +05301017
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +05301023}
1024
1025func (PONRMgr *PONResourceManager) GenerateNextID(Resource map[string]interface{}) (uint32, error) {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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 }
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +05301041
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +05301055}
1056
1057func (PONRMgr *PONResourceManager) ReleaseID(Resource map[string]interface{}, Id uint32) bool {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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)
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +05301077
Kent Hagerman0ab4cb22019-04-24 13:13:35 -04001078 return true
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +05301079}
1080
Kent Hagerman0ab4cb22019-04-24 13:13:35 -04001081func (PONRMgr *PONResourceManager) GetTechnology() string {
1082 return PONRMgr.Technology
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +05301083}
1084
Kent Hagerman0ab4cb22019-04-24 13:13:35 -04001085func (PONRMgr *PONResourceManager) GetResourceTypeAllocID() string {
1086 return ALLOC_ID
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +05301087}
1088
Kent Hagerman0ab4cb22019-04-24 13:13:35 -04001089func (PONRMgr *PONResourceManager) GetResourceTypeGemPortID() string {
1090 return GEMPORT_ID
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +05301091}
1092
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +05301093// 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) {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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 }
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +05301104}
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) {
Kent Hagerman0ab4cb22019-04-24 13:13:35 -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 }
Abhilash S.Laxmeshwar068867d2019-03-15 16:55:19 +05301117}