blob: 5c10b5eb0c8757bf1b6f0f1c5c7232040f567d3e [file] [log] [blame]
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001/*
2 * Copyright 2019-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package ponresourcemanager
18
19import (
npujarec5762e2020-01-01 14:08:48 +053020 "context"
Matt Jeanneret384d8c92019-05-06 14:27:31 -040021 "encoding/base64"
22 "encoding/json"
23 "errors"
24 "fmt"
Neha Sharmacc656962020-04-14 14:26:11 +000025 "time"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040026
Esin Karamanccb714b2019-11-29 15:02:06 +000027 bitmap "github.com/boljen/go-bitmap"
28 "github.com/opencord/voltha-lib-go/v3/pkg/db"
29 "github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore"
30 "github.com/opencord/voltha-lib-go/v3/pkg/log"
31 tp "github.com/opencord/voltha-lib-go/v3/pkg/techprofile"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040032)
33
34const (
Matt Jeanneret384d8c92019-05-06 14:27:31 -040035 //Constants to identify resource pool
36 UNI_ID = "UNI_ID"
37 ONU_ID = "ONU_ID"
38 ALLOC_ID = "ALLOC_ID"
39 GEMPORT_ID = "GEMPORT_ID"
40 FLOW_ID = "FLOW_ID"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040041
Matt Jeanneret384d8c92019-05-06 14:27:31 -040042 //Constants for passing command line arugments
43 OLT_MODEL_ARG = "--olt_model"
44 PATH_PREFIX = "service/voltha/resource_manager/{%s}"
divyadesaid26f6b12020-03-19 06:30:28 +000045
46 /*The path under which configuration data is stored is defined as technology/device agnostic.
47 That means the path does not include any specific technology/device variable. Using technology/device
48 agnostic path also makes northbound applications, that need to write to this path,
49 technology/device agnostic.
50
51 Default kv client of PonResourceManager reads from/writes to PATH_PREFIX defined above.
52 That is why, an additional kv client (named KVStoreForConfig) is defined to read from the config path.
53 */
54 PATH_PREFIX_FOR_CONFIG = "service/voltha/resource_manager/config"
Matt Jeanneret384d8c92019-05-06 14:27:31 -040055 /*The resource ranges for a given device model should be placed
56 at 'resource_manager/<technology>/resource_ranges/<olt_model_type>'
57 path on the KV store.
58 If Resource Range parameters are to be read from the external KV store,
59 they are expected to be stored in the following format.
60 Note: All parameters are MANDATORY for now.
61 constants used as keys to reference the resource range parameters from
62 and external KV store.
63 */
64 UNI_ID_START_IDX = "uni_id_start"
65 UNI_ID_END_IDX = "uni_id_end"
66 ONU_ID_START_IDX = "onu_id_start"
67 ONU_ID_END_IDX = "onu_id_end"
68 ONU_ID_SHARED_IDX = "onu_id_shared"
69 ALLOC_ID_START_IDX = "alloc_id_start"
70 ALLOC_ID_END_IDX = "alloc_id_end"
71 ALLOC_ID_SHARED_IDX = "alloc_id_shared"
72 GEMPORT_ID_START_IDX = "gemport_id_start"
73 GEMPORT_ID_END_IDX = "gemport_id_end"
74 GEMPORT_ID_SHARED_IDX = "gemport_id_shared"
75 FLOW_ID_START_IDX = "flow_id_start"
76 FLOW_ID_END_IDX = "flow_id_end"
77 FLOW_ID_SHARED_IDX = "flow_id_shared"
78 NUM_OF_PON_PORT = "pon_ports"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040079
Matt Jeanneret384d8c92019-05-06 14:27:31 -040080 /*
81 The KV store backend is initialized with a path prefix and we need to
82 provide only the suffix.
83 */
84 PON_RESOURCE_RANGE_CONFIG_PATH = "resource_ranges/%s"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040085
Matt Jeanneret384d8c92019-05-06 14:27:31 -040086 //resource path suffix
87 //Path on the KV store for storing alloc id ranges and resource pool for a given interface
88 //Format: <device_id>/alloc_id_pool/<pon_intf_id>
89 ALLOC_ID_POOL_PATH = "{%s}/alloc_id_pool/{%d}"
90 //Path on the KV store for storing gemport id ranges and resource pool for a given interface
91 //Format: <device_id>/gemport_id_pool/<pon_intf_id>
92 GEMPORT_ID_POOL_PATH = "{%s}/gemport_id_pool/{%d}"
93 //Path on the KV store for storing onu id ranges and resource pool for a given interface
94 //Format: <device_id>/onu_id_pool/<pon_intf_id>
95 ONU_ID_POOL_PATH = "{%s}/onu_id_pool/{%d}"
96 //Path on the KV store for storing flow id ranges and resource pool for a given interface
97 //Format: <device_id>/flow_id_pool/<pon_intf_id>
98 FLOW_ID_POOL_PATH = "{%s}/flow_id_pool/{%d}"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040099
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400100 //Path on the KV store for storing list of alloc IDs for a given ONU
101 //Format: <device_id>/<(pon_intf_id, onu_id)>/alloc_ids
102 ALLOC_ID_RESOURCE_MAP_PATH = "{%s}/{%s}/alloc_ids"
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400103
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400104 //Path on the KV store for storing list of gemport IDs for a given ONU
105 //Format: <device_id>/<(pon_intf_id, onu_id)>/gemport_ids
106 GEMPORT_ID_RESOURCE_MAP_PATH = "{%s}/{%s}/gemport_ids"
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400107
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400108 //Path on the KV store for storing list of Flow IDs for a given ONU
109 //Format: <device_id>/<(pon_intf_id, onu_id)>/flow_ids
110 FLOW_ID_RESOURCE_MAP_PATH = "{%s}/{%s}/flow_ids"
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400111
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400112 //Flow Id info: Use to store more metadata associated with the flow_id
113 //Format: <device_id>/<(pon_intf_id, onu_id)>/flow_id_info/<flow_id>
114 FLOW_ID_INFO_PATH = "{%s}/{%s}/flow_id_info/{%d}"
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400115
Scott Bakerc6e54cb2019-11-04 09:31:25 -0800116 //path on the kvstore to store onugem info map
117 //format: <device-id>/onu_gem_info/<intfid>
118 ONU_GEM_INFO_PATH = "{%s}/onu_gem_info/{%d}" // onu_gem/<(intfid)>
119
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400120 //Constants for internal usage.
121 PON_INTF_ID = "pon_intf_id"
122 START_IDX = "start_idx"
123 END_IDX = "end_idx"
124 POOL = "pool"
125 NUM_OF_PON_INTF = 16
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400126
Neha Sharmacc656962020-04-14 14:26:11 +0000127 KVSTORE_RETRY_TIMEOUT = 5 * time.Second
divyadesaid26f6b12020-03-19 06:30:28 +0000128 //Path on the KV store for storing reserved gem ports
129 //Format: reserved_gemport_ids
130 RESERVED_GEMPORT_IDS_PATH = "reserved_gemport_ids"
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400131)
132
133//type ResourceTypeIndex string
134//type ResourceType string
135
136type PONResourceManager struct {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400137 //Implements APIs to initialize/allocate/release alloc/gemport/onu IDs.
divyadesaid26f6b12020-03-19 06:30:28 +0000138 Technology string
139 DeviceType string
140 DeviceID string
141 Backend string // ETCD, or consul
Neha Sharma3f221ae2020-04-29 19:02:12 +0000142 Address string // address of the KV store
divyadesaid26f6b12020-03-19 06:30:28 +0000143 OLTModel string
144 KVStore *db.Backend
145 KVStoreForConfig *db.Backend
146 TechProfileMgr tp.TechProfileIf // create object of *tp.TechProfileMgr
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400147
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400148 // Below attribute, pon_resource_ranges, should be initialized
149 // by reading from KV store.
150 PonResourceRanges map[string]interface{}
151 SharedResourceMgrs map[string]*PONResourceManager
152 SharedIdxByType map[string]string
153 IntfIDs []uint32 // list of pon interface IDs
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400154 Globalorlocal string
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400155}
156
Neha Sharmacc656962020-04-14 14:26:11 +0000157func newKVClient(storeType string, address string, timeout time.Duration) (kvstore.Client, error) {
Scott Baker24f83e22020-03-30 16:14:28 -0700158 logger.Infow("kv-store-type", log.Fields{"store": storeType})
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400159 switch storeType {
160 case "consul":
161 return kvstore.NewConsulClient(address, timeout)
162 case "etcd":
Scott Bakered4a8e72020-04-17 11:10:20 -0700163 return kvstore.NewEtcdClient(address, timeout, log.WarnLevel)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400164 }
165 return nil, errors.New("unsupported-kv-store")
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400166}
167
Neha Sharma3f221ae2020-04-29 19:02:12 +0000168func SetKVClient(Technology string, Backend string, Addr string, configClient bool) *db.Backend {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400169 // TODO : Make sure direct call to NewBackend is working fine with backend , currently there is some
170 // issue between kv store and backend , core is not calling NewBackend directly
Neha Sharma3f221ae2020-04-29 19:02:12 +0000171 kvClient, err := newKVClient(Backend, Addr, KVSTORE_RETRY_TIMEOUT)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400172 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700173 logger.Fatalw("Failed to init KV client\n", log.Fields{"err": err})
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400174 return nil
175 }
divyadesaid26f6b12020-03-19 06:30:28 +0000176
177 var pathPrefix string
178 if configClient {
179 pathPrefix = PATH_PREFIX_FOR_CONFIG
180 } else {
181 pathPrefix = fmt.Sprintf(PATH_PREFIX, Technology)
182 }
183
sbarbaria8910ba2019-11-05 10:12:23 -0500184 kvbackend := &db.Backend{
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400185 Client: kvClient,
186 StoreType: Backend,
Neha Sharma3f221ae2020-04-29 19:02:12 +0000187 Address: Addr,
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400188 Timeout: KVSTORE_RETRY_TIMEOUT,
divyadesaid26f6b12020-03-19 06:30:28 +0000189 PathPrefix: pathPrefix}
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400190
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400191 return kvbackend
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400192}
193
194// NewPONResourceManager creates a new PON resource manager.
Neha Sharma3f221ae2020-04-29 19:02:12 +0000195func NewPONResourceManager(Technology string, DeviceType string, DeviceID string, Backend string, Address string) (*PONResourceManager, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400196 var PONMgr PONResourceManager
197 PONMgr.Technology = Technology
198 PONMgr.DeviceType = DeviceType
199 PONMgr.DeviceID = DeviceID
200 PONMgr.Backend = Backend
Neha Sharma3f221ae2020-04-29 19:02:12 +0000201 PONMgr.Address = Address
202 PONMgr.KVStore = SetKVClient(Technology, Backend, Address, false)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400203 if PONMgr.KVStore == nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700204 logger.Error("KV Client initilization failed")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400205 return nil, errors.New("Failed to init KV client")
206 }
divyadesaid26f6b12020-03-19 06:30:28 +0000207 // init kv client to read from the config path
Neha Sharma3f221ae2020-04-29 19:02:12 +0000208 PONMgr.KVStoreForConfig = SetKVClient(Technology, Backend, Address, true)
divyadesaid26f6b12020-03-19 06:30:28 +0000209 if PONMgr.KVStoreForConfig == nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700210 logger.Error("KV Config Client initilization failed")
divyadesaid26f6b12020-03-19 06:30:28 +0000211 return nil, errors.New("Failed to init KV Config client")
212 }
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400213 // Initialize techprofile for this technology
Neha Sharma3f221ae2020-04-29 19:02:12 +0000214 if PONMgr.TechProfileMgr, _ = tp.NewTechProfile(&PONMgr, Backend, Address); PONMgr.TechProfileMgr == nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700215 logger.Error("Techprofile initialization failed")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400216 return nil, errors.New("Failed to init tech profile")
217 }
218 PONMgr.PonResourceRanges = make(map[string]interface{})
219 PONMgr.SharedResourceMgrs = make(map[string]*PONResourceManager)
220 PONMgr.SharedIdxByType = make(map[string]string)
221 PONMgr.SharedIdxByType[ONU_ID] = ONU_ID_SHARED_IDX
222 PONMgr.SharedIdxByType[ALLOC_ID] = ALLOC_ID_SHARED_IDX
223 PONMgr.SharedIdxByType[GEMPORT_ID] = GEMPORT_ID_SHARED_IDX
224 PONMgr.SharedIdxByType[FLOW_ID] = FLOW_ID_SHARED_IDX
225 PONMgr.IntfIDs = make([]uint32, NUM_OF_PON_INTF)
226 PONMgr.OLTModel = DeviceType
227 return &PONMgr, nil
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400228}
229
230/*
231 Initialize PON resource ranges with config fetched from kv store.
232 return boolean: True if PON resource ranges initialized else false
233 Try to initialize the PON Resource Ranges from KV store based on the
234 OLT model key, if available
235*/
236
npujarec5762e2020-01-01 14:08:48 +0530237func (PONRMgr *PONResourceManager) InitResourceRangesFromKVStore(ctx context.Context) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400238 //Initialize PON resource ranges with config fetched from kv store.
239 //:return boolean: True if PON resource ranges initialized else false
240 // Try to initialize the PON Resource Ranges from KV store based on the
241 // OLT model key, if available
242 if PONRMgr.OLTModel == "" {
Scott Baker24f83e22020-03-30 16:14:28 -0700243 logger.Error("Failed to get OLT model")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400244 return false
245 }
246 Path := fmt.Sprintf(PON_RESOURCE_RANGE_CONFIG_PATH, PONRMgr.OLTModel)
247 //get resource from kv store
npujarec5762e2020-01-01 14:08:48 +0530248 Result, err := PONRMgr.KVStore.Get(ctx, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400249 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700250 logger.Debugf("Error in fetching resource %s from KV strore", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400251 return false
252 }
253 if Result == nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700254 logger.Debug("There may be no resources in the KV store in case of fresh bootup, return true")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400255 return false
256 }
257 //update internal ranges from kv ranges. If there are missing
258 // values in the KV profile, continue to use the defaults
259 Value, err := ToByte(Result.Value)
260 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700261 logger.Error("Failed to convert kvpair to byte string")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400262 return false
263 }
264 if err := json.Unmarshal(Value, &PONRMgr.PonResourceRanges); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700265 logger.Error("Failed to Unmarshal json byte")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400266 return false
267 }
Scott Baker24f83e22020-03-30 16:14:28 -0700268 logger.Debug("Init resource ranges from kvstore success")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400269 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400270}
271
272func (PONRMgr *PONResourceManager) UpdateRanges(StartIDx string, StartID uint32, EndIDx string, EndID uint32,
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400273 SharedIDx string, SharedPoolID uint32, RMgr *PONResourceManager) {
274 /*
275 Update the ranges for all reosurce type in the intermnal maps
276 param: resource type start index
277 param: start ID
278 param: resource type end index
279 param: end ID
280 param: resource type shared index
281 param: shared pool id
282 param: global resource manager
283 */
Scott Baker24f83e22020-03-30 16:14:28 -0700284 logger.Debugf("update ranges for %s, %d", StartIDx, StartID)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400285
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400286 if StartID != 0 {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400287 if (PONRMgr.PonResourceRanges[StartIDx] == nil) || (PONRMgr.PonResourceRanges[StartIDx].(uint32) < StartID) {
288 PONRMgr.PonResourceRanges[StartIDx] = StartID
289 }
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400290 }
291 if EndID != 0 {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400292 if (PONRMgr.PonResourceRanges[EndIDx] == nil) || (PONRMgr.PonResourceRanges[EndIDx].(uint32) > EndID) {
293 PONRMgr.PonResourceRanges[EndIDx] = EndID
294 }
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400295 }
296 //if SharedPoolID != 0 {
297 PONRMgr.PonResourceRanges[SharedIDx] = SharedPoolID
298 //}
299 if RMgr != nil {
300 PONRMgr.SharedResourceMgrs[SharedIDx] = RMgr
301 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400302}
303
304func (PONRMgr *PONResourceManager) InitDefaultPONResourceRanges(ONUIDStart uint32,
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400305 ONUIDEnd uint32,
306 ONUIDSharedPoolID uint32,
307 AllocIDStart uint32,
308 AllocIDEnd uint32,
309 AllocIDSharedPoolID uint32,
310 GEMPortIDStart uint32,
311 GEMPortIDEnd uint32,
312 GEMPortIDSharedPoolID uint32,
313 FlowIDStart uint32,
314 FlowIDEnd uint32,
315 FlowIDSharedPoolID uint32,
316 UNIIDStart uint32,
317 UNIIDEnd uint32,
318 NoOfPONPorts uint32,
319 IntfIDs []uint32) bool {
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400320
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400321 /*Initialize default PON resource ranges
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400322
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400323 :param onu_id_start_idx: onu id start index
324 :param onu_id_end_idx: onu id end index
325 :param onu_id_shared_pool_id: pool idx for id shared by all intfs or None for no sharing
326 :param alloc_id_start_idx: alloc id start index
327 :param alloc_id_end_idx: alloc id end index
328 :param alloc_id_shared_pool_id: pool idx for alloc id shared by all intfs or None for no sharing
329 :param gemport_id_start_idx: gemport id start index
330 :param gemport_id_end_idx: gemport id end index
331 :param gemport_id_shared_pool_id: pool idx for gemport id shared by all intfs or None for no sharing
332 :param flow_id_start_idx: flow id start index
333 :param flow_id_end_idx: flow id end index
334 :param flow_id_shared_pool_id: pool idx for flow id shared by all intfs or None for no sharing
335 :param num_of_pon_ports: number of PON ports
336 :param intf_ids: interfaces serviced by this manager
337 */
338 PONRMgr.UpdateRanges(ONU_ID_START_IDX, ONUIDStart, ONU_ID_END_IDX, ONUIDEnd, ONU_ID_SHARED_IDX, ONUIDSharedPoolID, nil)
339 PONRMgr.UpdateRanges(ALLOC_ID_START_IDX, AllocIDStart, ALLOC_ID_END_IDX, AllocIDEnd, ALLOC_ID_SHARED_IDX, AllocIDSharedPoolID, nil)
340 PONRMgr.UpdateRanges(GEMPORT_ID_START_IDX, GEMPortIDStart, GEMPORT_ID_END_IDX, GEMPortIDEnd, GEMPORT_ID_SHARED_IDX, GEMPortIDSharedPoolID, nil)
341 PONRMgr.UpdateRanges(FLOW_ID_START_IDX, FlowIDStart, FLOW_ID_END_IDX, FlowIDEnd, FLOW_ID_SHARED_IDX, FlowIDSharedPoolID, nil)
342 PONRMgr.UpdateRanges(UNI_ID_START_IDX, UNIIDStart, UNI_ID_END_IDX, UNIIDEnd, "", 0, nil)
Scott Baker24f83e22020-03-30 16:14:28 -0700343 logger.Debug("Initialize default range values")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400344 var i uint32
345 if IntfIDs == nil {
346 for i = 0; i < NoOfPONPorts; i++ {
347 PONRMgr.IntfIDs = append(PONRMgr.IntfIDs, i)
348 }
349 } else {
350 PONRMgr.IntfIDs = IntfIDs
351 }
352 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400353}
354
npujarec5762e2020-01-01 14:08:48 +0530355func (PONRMgr *PONResourceManager) InitDeviceResourcePool(ctx context.Context) error {
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400356
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400357 //Initialize resource pool for all PON ports.
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400358
Scott Baker24f83e22020-03-30 16:14:28 -0700359 logger.Debug("Init resource ranges")
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400360
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400361 var err error
362 for _, Intf := range PONRMgr.IntfIDs {
363 SharedPoolID := PONRMgr.PonResourceRanges[ONU_ID_SHARED_IDX].(uint32)
364 if SharedPoolID != 0 {
365 Intf = SharedPoolID
366 }
npujarec5762e2020-01-01 14:08:48 +0530367 if err = PONRMgr.InitResourceIDPool(ctx, Intf, ONU_ID,
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400368 PONRMgr.PonResourceRanges[ONU_ID_START_IDX].(uint32),
369 PONRMgr.PonResourceRanges[ONU_ID_END_IDX].(uint32)); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700370 logger.Error("Failed to init ONU ID resource pool")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400371 return err
372 }
373 if SharedPoolID != 0 {
374 break
375 }
376 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400377
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400378 for _, Intf := range PONRMgr.IntfIDs {
379 SharedPoolID := PONRMgr.PonResourceRanges[ALLOC_ID_SHARED_IDX].(uint32)
380 if SharedPoolID != 0 {
381 Intf = SharedPoolID
382 }
npujarec5762e2020-01-01 14:08:48 +0530383 if err = PONRMgr.InitResourceIDPool(ctx, Intf, ALLOC_ID,
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400384 PONRMgr.PonResourceRanges[ALLOC_ID_START_IDX].(uint32),
385 PONRMgr.PonResourceRanges[ALLOC_ID_END_IDX].(uint32)); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700386 logger.Error("Failed to init ALLOC ID resource pool ")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400387 return err
388 }
389 if SharedPoolID != 0 {
390 break
391 }
392 }
393 for _, Intf := range PONRMgr.IntfIDs {
394 SharedPoolID := PONRMgr.PonResourceRanges[GEMPORT_ID_SHARED_IDX].(uint32)
395 if SharedPoolID != 0 {
396 Intf = SharedPoolID
397 }
npujarec5762e2020-01-01 14:08:48 +0530398 if err = PONRMgr.InitResourceIDPool(ctx, Intf, GEMPORT_ID,
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400399 PONRMgr.PonResourceRanges[GEMPORT_ID_START_IDX].(uint32),
400 PONRMgr.PonResourceRanges[GEMPORT_ID_END_IDX].(uint32)); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700401 logger.Error("Failed to init GEMPORT ID resource pool")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400402 return err
403 }
404 if SharedPoolID != 0 {
405 break
406 }
407 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400408
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400409 for _, Intf := range PONRMgr.IntfIDs {
410 SharedPoolID := PONRMgr.PonResourceRanges[FLOW_ID_SHARED_IDX].(uint32)
411 if SharedPoolID != 0 {
412 Intf = SharedPoolID
413 }
npujarec5762e2020-01-01 14:08:48 +0530414 if err = PONRMgr.InitResourceIDPool(ctx, Intf, FLOW_ID,
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400415 PONRMgr.PonResourceRanges[FLOW_ID_START_IDX].(uint32),
416 PONRMgr.PonResourceRanges[FLOW_ID_END_IDX].(uint32)); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700417 logger.Error("Failed to init FLOW ID resource pool")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400418 return err
419 }
420 if SharedPoolID != 0 {
421 break
422 }
423 }
424 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400425}
426
npujarec5762e2020-01-01 14:08:48 +0530427func (PONRMgr *PONResourceManager) ClearDeviceResourcePool(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -0400428
429 //Clear resource pool for all PON ports.
430
Scott Baker24f83e22020-03-30 16:14:28 -0700431 logger.Debug("Clear resource ranges")
Devmalya Paul495b94a2019-08-27 19:42:00 -0400432
433 for _, Intf := range PONRMgr.IntfIDs {
434 SharedPoolID := PONRMgr.PonResourceRanges[ONU_ID_SHARED_IDX].(uint32)
435 if SharedPoolID != 0 {
436 Intf = SharedPoolID
437 }
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000438 if status := PONRMgr.ClearResourceIDPool(ctx, Intf, ONU_ID); !status {
Scott Baker24f83e22020-03-30 16:14:28 -0700439 logger.Error("Failed to clear ONU ID resource pool")
Devmalya Paul495b94a2019-08-27 19:42:00 -0400440 return errors.New("Failed to clear ONU ID resource pool")
441 }
442 if SharedPoolID != 0 {
443 break
444 }
445 }
446
447 for _, Intf := range PONRMgr.IntfIDs {
448 SharedPoolID := PONRMgr.PonResourceRanges[ALLOC_ID_SHARED_IDX].(uint32)
449 if SharedPoolID != 0 {
450 Intf = SharedPoolID
451 }
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000452 if status := PONRMgr.ClearResourceIDPool(ctx, Intf, ALLOC_ID); !status {
Scott Baker24f83e22020-03-30 16:14:28 -0700453 logger.Error("Failed to clear ALLOC ID resource pool ")
Devmalya Paul495b94a2019-08-27 19:42:00 -0400454 return errors.New("Failed to clear ALLOC ID resource pool")
455 }
456 if SharedPoolID != 0 {
457 break
458 }
459 }
460 for _, Intf := range PONRMgr.IntfIDs {
461 SharedPoolID := PONRMgr.PonResourceRanges[GEMPORT_ID_SHARED_IDX].(uint32)
462 if SharedPoolID != 0 {
463 Intf = SharedPoolID
464 }
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000465 if status := PONRMgr.ClearResourceIDPool(ctx, Intf, GEMPORT_ID); !status {
Scott Baker24f83e22020-03-30 16:14:28 -0700466 logger.Error("Failed to clear GEMPORT ID resource pool")
Devmalya Paul495b94a2019-08-27 19:42:00 -0400467 return errors.New("Failed to clear GEMPORT ID resource pool")
468 }
469 if SharedPoolID != 0 {
470 break
471 }
472 }
473
474 for _, Intf := range PONRMgr.IntfIDs {
475 SharedPoolID := PONRMgr.PonResourceRanges[FLOW_ID_SHARED_IDX].(uint32)
476 if SharedPoolID != 0 {
477 Intf = SharedPoolID
478 }
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000479 if status := PONRMgr.ClearResourceIDPool(ctx, Intf, FLOW_ID); !status {
Scott Baker24f83e22020-03-30 16:14:28 -0700480 logger.Error("Failed to clear FLOW ID resource pool")
Devmalya Paul495b94a2019-08-27 19:42:00 -0400481 return errors.New("Failed to clear FLOW ID resource pool")
482 }
483 if SharedPoolID != 0 {
484 break
485 }
486 }
487 return nil
488}
489
npujarec5762e2020-01-01 14:08:48 +0530490func (PONRMgr *PONResourceManager) InitResourceIDPool(ctx context.Context, Intf uint32, ResourceType string, StartID uint32, EndID uint32) error {
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400491
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400492 /*Initialize Resource ID pool for a given Resource Type on a given PON Port
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400493
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400494 :param pon_intf_id: OLT PON interface id
495 :param resource_type: String to identify type of resource
496 :param start_idx: start index for onu id pool
497 :param end_idx: end index for onu id pool
498 :return boolean: True if resource id pool initialized else false
499 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400500
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400501 // delegate to the master instance if sharing enabled across instances
502 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
503 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
npujarec5762e2020-01-01 14:08:48 +0530504 return SharedResourceMgr.InitResourceIDPool(ctx, Intf, ResourceType, StartID, EndID)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400505 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400506
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400507 Path := PONRMgr.GetPath(Intf, ResourceType)
508 if Path == "" {
Scott Baker24f83e22020-03-30 16:14:28 -0700509 logger.Errorf("Failed to get path for resource type %s", ResourceType)
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000510 return fmt.Errorf("Failed to get path for resource type %s", ResourceType)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400511 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400512
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400513 //In case of adapter reboot and reconciliation resource in kv store
514 //checked for its presence if not kv store update happens
npujarec5762e2020-01-01 14:08:48 +0530515 Res, err := PONRMgr.GetResource(ctx, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400516 if (err == nil) && (Res != nil) {
Scott Baker24f83e22020-03-30 16:14:28 -0700517 logger.Debugf("Resource %s already present in store ", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400518 return nil
519 } else {
divyadesaid26f6b12020-03-19 06:30:28 +0000520 var excluded []uint32
521 if ResourceType == GEMPORT_ID {
522 //get gem port ids defined in the KV store, if any, and exclude them from the gem port id pool
523 if reservedGemPortIds, defined := PONRMgr.getReservedGemPortIdsFromKVStore(ctx); defined {
524 excluded = reservedGemPortIds
Scott Baker24f83e22020-03-30 16:14:28 -0700525 logger.Debugw("Excluding some ports from GEM port id pool", log.Fields{"excluded gem ports": excluded})
divyadesaid26f6b12020-03-19 06:30:28 +0000526 }
527 }
528 FormatResult, err := PONRMgr.FormatResource(Intf, StartID, EndID, excluded)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400529 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700530 logger.Errorf("Failed to format resource")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400531 return err
532 }
533 // Add resource as json in kv store.
npujarec5762e2020-01-01 14:08:48 +0530534 err = PONRMgr.KVStore.Put(ctx, Path, FormatResult)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400535 if err == nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700536 logger.Debug("Successfuly posted to kv store")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400537 return err
538 }
539 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400540
Scott Baker24f83e22020-03-30 16:14:28 -0700541 logger.Debug("Error initializing pool")
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400542
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400543 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400544}
545
divyadesaid26f6b12020-03-19 06:30:28 +0000546func (PONRMgr *PONResourceManager) getReservedGemPortIdsFromKVStore(ctx context.Context) ([]uint32, bool) {
547 var reservedGemPortIds []uint32
548 // read reserved gem ports from the config path
549 KvPair, err := PONRMgr.KVStoreForConfig.Get(ctx, RESERVED_GEMPORT_IDS_PATH)
550 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700551 logger.Errorw("Unable to get reserved GEM port ids from the kv store", log.Fields{"err": err})
divyadesaid26f6b12020-03-19 06:30:28 +0000552 return reservedGemPortIds, false
553 }
554 if KvPair == nil || KvPair.Value == nil {
555 //no reserved gem port defined in the store
556 return reservedGemPortIds, false
557 }
558 Val, err := kvstore.ToByte(KvPair.Value)
559 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700560 logger.Errorw("Failed to convert reserved gem port ids into byte array", log.Fields{"err": err})
divyadesaid26f6b12020-03-19 06:30:28 +0000561 return reservedGemPortIds, false
562 }
563 if err = json.Unmarshal(Val, &reservedGemPortIds); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700564 logger.Errorw("Failed to unmarshal reservedGemPortIds", log.Fields{"err": err})
divyadesaid26f6b12020-03-19 06:30:28 +0000565 return reservedGemPortIds, false
566 }
567 return reservedGemPortIds, true
568}
569
570func (PONRMgr *PONResourceManager) FormatResource(IntfID uint32, StartIDx uint32, EndIDx uint32,
571 Excluded []uint32) ([]byte, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400572 /*
573 Format resource as json.
574 :param pon_intf_id: OLT PON interface id
575 :param start_idx: start index for id pool
576 :param end_idx: end index for id pool
divyadesaid26f6b12020-03-19 06:30:28 +0000577 :Id values to be Excluded from the pool
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400578 :return dictionary: resource formatted as map
579 */
580 // Format resource as json to be stored in backend store
581 Resource := make(map[string]interface{})
582 Resource[PON_INTF_ID] = IntfID
583 Resource[START_IDX] = StartIDx
584 Resource[END_IDX] = EndIDx
585 /*
586 Resource pool stored in backend store as binary string.
587 Tracking the resource allocation will be done by setting the bits \
588 in the byte array. The index set will be the resource number allocated.
589 */
590 var TSData *bitmap.Threadsafe
591 if TSData = bitmap.NewTS(int(EndIDx)); TSData == nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700592 logger.Error("Failed to create a bitmap")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400593 return nil, errors.New("Failed to create bitmap")
594 }
divyadesaid26f6b12020-03-19 06:30:28 +0000595 for _, excludedID := range Excluded {
596 if excludedID < StartIDx || excludedID > EndIDx {
Scott Baker24f83e22020-03-30 16:14:28 -0700597 logger.Warnf("Cannot reserve %d. It must be in the range of [%d, %d]", excludedID,
divyadesaid26f6b12020-03-19 06:30:28 +0000598 StartIDx, EndIDx)
599 continue
600 }
601 PONRMgr.reserveID(TSData, StartIDx, excludedID)
602 }
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400603 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 -0400604
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400605 Value, err := json.Marshal(Resource)
606 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700607 logger.Errorf("Failed to marshall resource")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400608 return nil, err
609 }
610 return Value, err
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400611}
npujarec5762e2020-01-01 14:08:48 +0530612func (PONRMgr *PONResourceManager) GetResource(ctx context.Context, Path string) (map[string]interface{}, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400613 /*
614 Get resource from kv store.
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400615
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400616 :param path: path to get resource
617 :return: resource if resource present in kv store else None
618 */
619 //get resource from kv store
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400620
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400621 var Value []byte
622 Result := make(map[string]interface{})
623 var Str string
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400624
npujarec5762e2020-01-01 14:08:48 +0530625 Resource, err := PONRMgr.KVStore.Get(ctx, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400626 if (err != nil) || (Resource == nil) {
Scott Baker24f83e22020-03-30 16:14:28 -0700627 logger.Debugf("Resource unavailable at %s", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400628 return nil, err
629 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400630
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400631 Value, err = ToByte(Resource.Value)
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000632 if err != nil {
633 return nil, err
634 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400635
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400636 // decode resource fetched from backend store to dictionary
637 err = json.Unmarshal(Value, &Result)
638 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700639 logger.Error("Failed to decode resource")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400640 return Result, err
641 }
642 /*
643 resource pool in backend store stored as binary string whereas to
644 access the pool to generate/release IDs it need to be converted
645 as BitArray
646 */
647 Str, err = ToString(Result[POOL])
648 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700649 logger.Error("Failed to conver to kv pair to string")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400650 return Result, err
651 }
652 Decode64, _ := base64.StdEncoding.DecodeString(Str)
653 Result[POOL], err = ToByte(Decode64)
654 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700655 logger.Error("Failed to convert resource pool to byte")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400656 return Result, err
657 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400658
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400659 return Result, err
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400660}
661
662func (PONRMgr *PONResourceManager) GetPath(IntfID uint32, ResourceType string) string {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400663 /*
664 Get path for given resource type.
665 :param pon_intf_id: OLT PON interface id
666 :param resource_type: String to identify type of resource
667 :return: path for given resource type
668 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400669
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400670 /*
671 Get the shared pool for the given resource type.
672 all the resource ranges and the shared resource maps are initialized during the init.
673 */
674 SharedPoolID := PONRMgr.PonResourceRanges[PONRMgr.SharedIdxByType[ResourceType]].(uint32)
675 if SharedPoolID != 0 {
676 IntfID = SharedPoolID
677 }
678 var Path string
679 if ResourceType == ONU_ID {
680 Path = fmt.Sprintf(ONU_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
681 } else if ResourceType == ALLOC_ID {
682 Path = fmt.Sprintf(ALLOC_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
683 } else if ResourceType == GEMPORT_ID {
684 Path = fmt.Sprintf(GEMPORT_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
685 } else if ResourceType == FLOW_ID {
686 Path = fmt.Sprintf(FLOW_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
687 } else {
Scott Baker24f83e22020-03-30 16:14:28 -0700688 logger.Error("Invalid resource pool identifier")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400689 }
690 return Path
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400691}
692
npujarec5762e2020-01-01 14:08:48 +0530693func (PONRMgr *PONResourceManager) GetResourceID(ctx context.Context, IntfID uint32, ResourceType string, NumIDs uint32) ([]uint32, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400694 /*
695 Create alloc/gemport/onu/flow id for given OLT PON interface.
696 :param pon_intf_id: OLT PON interface id
697 :param resource_type: String to identify type of resource
698 :param num_of_id: required number of ids
699 :return list/uint32/None: list, uint32 or None if resource type is
700 alloc_id/gemport_id, onu_id or invalid type respectively
701 */
702 if NumIDs < 1 {
Scott Baker24f83e22020-03-30 16:14:28 -0700703 logger.Error("Invalid number of resources requested")
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000704 return nil, fmt.Errorf("Invalid number of resources requested %d", NumIDs)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400705 }
706 // delegate to the master instance if sharing enabled across instances
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400707
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400708 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
709 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
npujarec5762e2020-01-01 14:08:48 +0530710 return SharedResourceMgr.GetResourceID(ctx, IntfID, ResourceType, NumIDs)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400711 }
Scott Baker24f83e22020-03-30 16:14:28 -0700712 logger.Debugf("Fetching resource from %s rsrc mgr for resource %s", PONRMgr.Globalorlocal, ResourceType)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400713
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400714 Path := PONRMgr.GetPath(IntfID, ResourceType)
715 if Path == "" {
Scott Baker24f83e22020-03-30 16:14:28 -0700716 logger.Errorf("Failed to get path for resource type %s", ResourceType)
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000717 return nil, fmt.Errorf("Failed to get path for resource type %s", ResourceType)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400718 }
Scott Baker24f83e22020-03-30 16:14:28 -0700719 logger.Debugf("Get resource for type %s on path %s", ResourceType, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400720 var Result []uint32
721 var NextID uint32
npujarec5762e2020-01-01 14:08:48 +0530722 Resource, err := PONRMgr.GetResource(ctx, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400723 if (err == nil) && (ResourceType == ONU_ID) || (ResourceType == FLOW_ID) {
724 if NextID, err = PONRMgr.GenerateNextID(Resource); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700725 logger.Error("Failed to Generate ID")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400726 return Result, err
727 }
728 Result = append(Result, NextID)
729 } else if (err == nil) && ((ResourceType == GEMPORT_ID) || (ResourceType == ALLOC_ID)) {
730 if NumIDs == 1 {
731 if NextID, err = PONRMgr.GenerateNextID(Resource); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700732 logger.Error("Failed to Generate ID")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400733 return Result, err
734 }
735 Result = append(Result, NextID)
736 } else {
737 for NumIDs > 0 {
738 if NextID, err = PONRMgr.GenerateNextID(Resource); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700739 logger.Error("Failed to Generate ID")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400740 return Result, err
741 }
742 Result = append(Result, NextID)
743 NumIDs--
744 }
745 }
746 } else {
Scott Baker24f83e22020-03-30 16:14:28 -0700747 logger.Error("get resource failed")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400748 return Result, err
749 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400750
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400751 //Update resource in kv store
npujarec5762e2020-01-01 14:08:48 +0530752 if PONRMgr.UpdateResource(ctx, Path, Resource) != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700753 logger.Errorf("Failed to update resource %s", Path)
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000754 return nil, fmt.Errorf("Failed to update resource %s", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400755 }
756 return Result, nil
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400757}
758
759func checkValidResourceType(ResourceType string) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400760 KnownResourceTypes := []string{ONU_ID, ALLOC_ID, GEMPORT_ID, FLOW_ID}
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400761
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400762 for _, v := range KnownResourceTypes {
763 if v == ResourceType {
764 return true
765 }
766 }
767 return false
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400768}
769
npujarec5762e2020-01-01 14:08:48 +0530770func (PONRMgr *PONResourceManager) FreeResourceID(ctx context.Context, IntfID uint32, ResourceType string, ReleaseContent []uint32) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400771 /*
772 Release alloc/gemport/onu/flow id for given OLT PON interface.
773 :param pon_intf_id: OLT PON interface id
774 :param resource_type: String to identify type of resource
775 :param release_content: required number of ids
776 :return boolean: True if all IDs in given release_content release else False
777 */
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000778 if !checkValidResourceType(ResourceType) {
Scott Baker24f83e22020-03-30 16:14:28 -0700779 logger.Error("Invalid resource type")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400780 return false
781 }
782 if ReleaseContent == nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700783 logger.Debug("Nothing to release")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400784 return true
785 }
786 // delegate to the master instance if sharing enabled across instances
787 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
788 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
npujarec5762e2020-01-01 14:08:48 +0530789 return SharedResourceMgr.FreeResourceID(ctx, IntfID, ResourceType, ReleaseContent)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400790 }
791 Path := PONRMgr.GetPath(IntfID, ResourceType)
792 if Path == "" {
Scott Baker24f83e22020-03-30 16:14:28 -0700793 logger.Error("Failed to get path")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400794 return false
795 }
npujarec5762e2020-01-01 14:08:48 +0530796 Resource, err := PONRMgr.GetResource(ctx, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400797 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700798 logger.Error("Failed to get resource")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400799 return false
800 }
801 for _, Val := range ReleaseContent {
802 PONRMgr.ReleaseID(Resource, Val)
803 }
npujarec5762e2020-01-01 14:08:48 +0530804 if PONRMgr.UpdateResource(ctx, Path, Resource) != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700805 logger.Errorf("Free resource for %s failed", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400806 return false
807 }
808 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400809}
810
npujarec5762e2020-01-01 14:08:48 +0530811func (PONRMgr *PONResourceManager) UpdateResource(ctx context.Context, Path string, Resource map[string]interface{}) error {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400812 /*
813 Update resource in resource kv store.
814 :param path: path to update resource
815 :param resource: resource need to be updated
816 :return boolean: True if resource updated in kv store else False
817 */
818 // TODO resource[POOL] = resource[POOL].bin
819 Value, err := json.Marshal(Resource)
820 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700821 logger.Error("failed to Marshal")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400822 return err
823 }
npujarec5762e2020-01-01 14:08:48 +0530824 err = PONRMgr.KVStore.Put(ctx, Path, Value)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400825 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700826 logger.Error("failed to put data to kv store %s", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400827 return err
828 }
829 return nil
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400830}
831
npujarec5762e2020-01-01 14:08:48 +0530832func (PONRMgr *PONResourceManager) ClearResourceIDPool(ctx context.Context, contIntfID uint32, ResourceType string) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400833 /*
834 Clear Resource Pool for a given Resource Type on a given PON Port.
835 :return boolean: True if removed else False
836 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400837
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400838 // delegate to the master instance if sharing enabled across instances
839 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
840 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
npujarec5762e2020-01-01 14:08:48 +0530841 return SharedResourceMgr.ClearResourceIDPool(ctx, contIntfID, ResourceType)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400842 }
npujarec5762e2020-01-01 14:08:48 +0530843 Path := PONRMgr.GetPath(contIntfID, ResourceType)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400844 if Path == "" {
Scott Baker24f83e22020-03-30 16:14:28 -0700845 logger.Error("Failed to get path")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400846 return false
847 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400848
npujarec5762e2020-01-01 14:08:48 +0530849 if err := PONRMgr.KVStore.Delete(ctx, Path); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700850 logger.Errorf("Failed to delete resource %s", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400851 return false
852 }
Scott Baker24f83e22020-03-30 16:14:28 -0700853 logger.Debugf("Cleared resource %s", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400854 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400855}
856
npujarec5762e2020-01-01 14:08:48 +0530857func (PONRMgr PONResourceManager) InitResourceMap(ctx context.Context, PONIntfONUID string) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400858 /*
859 Initialize resource map
860 :param pon_intf_onu_id: reference of PON interface id and onu id
861 */
862 // initialize pon_intf_onu_id tuple to alloc_ids map
863 AllocIDPath := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
864 var AllocIDs []byte
npujarec5762e2020-01-01 14:08:48 +0530865 Result := PONRMgr.KVStore.Put(ctx, AllocIDPath, AllocIDs)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400866 if Result != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700867 logger.Error("Failed to update the KV store")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400868 return
869 }
870 // initialize pon_intf_onu_id tuple to gemport_ids map
871 GEMPortIDPath := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
872 var GEMPortIDs []byte
npujarec5762e2020-01-01 14:08:48 +0530873 Result = PONRMgr.KVStore.Put(ctx, GEMPortIDPath, GEMPortIDs)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400874 if Result != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700875 logger.Error("Failed to update the KV store")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400876 return
877 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400878}
879
npujarec5762e2020-01-01 14:08:48 +0530880func (PONRMgr PONResourceManager) RemoveResourceMap(ctx context.Context, PONIntfONUID string) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400881 /*
882 Remove resource map
883 :param pon_intf_onu_id: reference of PON interface id and onu id
884 */
885 // remove pon_intf_onu_id tuple to alloc_ids map
886 var err error
887 AllocIDPath := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
npujarec5762e2020-01-01 14:08:48 +0530888 if err = PONRMgr.KVStore.Delete(ctx, AllocIDPath); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700889 logger.Errorf("Failed to remove resource %s", AllocIDPath)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400890 return false
891 }
892 // remove pon_intf_onu_id tuple to gemport_ids map
893 GEMPortIDPath := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
npujarec5762e2020-01-01 14:08:48 +0530894 err = PONRMgr.KVStore.Delete(ctx, GEMPortIDPath)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400895 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700896 logger.Errorf("Failed to remove resource %s", GEMPortIDPath)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400897 return false
898 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400899
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400900 FlowIDPath := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
npujarec5762e2020-01-01 14:08:48 +0530901 if FlowIDs, err := PONRMgr.KVStore.List(ctx, FlowIDPath); err != nil {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400902 for _, Flow := range FlowIDs {
903 FlowIDInfoPath := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, PONIntfONUID, Flow.Value)
npujarec5762e2020-01-01 14:08:48 +0530904 if err = PONRMgr.KVStore.Delete(ctx, FlowIDInfoPath); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700905 logger.Errorf("Failed to remove resource %s", FlowIDInfoPath)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400906 return false
907 }
908 }
909 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400910
npujarec5762e2020-01-01 14:08:48 +0530911 if err = PONRMgr.KVStore.Delete(ctx, FlowIDPath); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700912 logger.Errorf("Failed to remove resource %s", FlowIDPath)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400913 return false
914 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400915
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400916 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400917}
918
npujarec5762e2020-01-01 14:08:48 +0530919func (PONRMgr *PONResourceManager) GetCurrentAllocIDForOnu(ctx context.Context, IntfONUID string) []uint32 {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400920 /*
921 Get currently configured alloc ids for given pon_intf_onu_id
922 :param pon_intf_onu_id: reference of PON interface id and onu id
923 :return list: List of alloc_ids if available, else None
924 */
925 Path := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400926
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400927 var Data []uint32
npujarec5762e2020-01-01 14:08:48 +0530928 Value, err := PONRMgr.KVStore.Get(ctx, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400929 if err == nil {
930 if Value != nil {
931 Val, err := ToByte(Value.Value)
932 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700933 logger.Errorw("Failed to convert into byte array", log.Fields{"error": err})
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400934 return Data
935 }
936 if err = json.Unmarshal(Val, &Data); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700937 logger.Error("Failed to unmarshal", log.Fields{"error": err})
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400938 return Data
939 }
940 }
941 }
942 return Data
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400943}
944
npujarec5762e2020-01-01 14:08:48 +0530945func (PONRMgr *PONResourceManager) GetCurrentGEMPortIDsForOnu(ctx context.Context, IntfONUID string) []uint32 {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400946 /*
947 Get currently configured gemport ids for given pon_intf_onu_id
948 :param pon_intf_onu_id: reference of PON interface id and onu id
949 :return list: List of gemport IDs if available, else None
950 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400951
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400952 Path := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
Scott Baker24f83e22020-03-30 16:14:28 -0700953 logger.Debugf("Getting current gemports for %s", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400954 var Data []uint32
npujarec5762e2020-01-01 14:08:48 +0530955 Value, err := PONRMgr.KVStore.Get(ctx, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400956 if err == nil {
957 if Value != nil {
958 Val, _ := ToByte(Value.Value)
959 if err = json.Unmarshal(Val, &Data); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700960 logger.Errorw("Failed to unmarshal", log.Fields{"error": err})
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400961 return Data
962 }
963 }
964 } else {
Scott Baker24f83e22020-03-30 16:14:28 -0700965 logger.Errorf("Failed to get data from kvstore for %s", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400966 }
967 return Data
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400968}
969
npujarec5762e2020-01-01 14:08:48 +0530970func (PONRMgr *PONResourceManager) GetCurrentFlowIDsForOnu(ctx context.Context, IntfONUID string) []uint32 {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400971 /*
972 Get currently configured flow ids for given pon_intf_onu_id
973 :param pon_intf_onu_id: reference of PON interface id and onu id
974 :return list: List of Flow IDs if available, else None
975 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400976
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400977 Path := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400978
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400979 var Data []uint32
npujarec5762e2020-01-01 14:08:48 +0530980 Value, err := PONRMgr.KVStore.Get(ctx, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400981 if err == nil {
982 if Value != nil {
983 Val, _ := ToByte(Value.Value)
984 if err = json.Unmarshal(Val, &Data); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700985 logger.Error("Failed to unmarshal")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400986 return Data
987 }
988 }
989 }
990 return Data
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400991}
992
npujarec5762e2020-01-01 14:08:48 +0530993func (PONRMgr *PONResourceManager) GetFlowIDInfo(ctx context.Context, IntfONUID string, FlowID uint32, Data interface{}) error {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400994 /*
995 Get flow details configured for the ONU.
996 :param pon_intf_onu_id: reference of PON interface id and onu id
997 :param flow_id: Flow Id reference
998 :param Data: Result
999 :return error: nil if no error in getting from KV store
1000 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001001
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001002 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001003
npujarec5762e2020-01-01 14:08:48 +05301004 Value, err := PONRMgr.KVStore.Get(ctx, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001005 if err == nil {
1006 if Value != nil {
1007 Val, err := ToByte(Value.Value)
1008 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001009 logger.Errorw("Failed to convert flowinfo into byte array", log.Fields{"error": err})
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001010 return err
1011 }
1012 if err = json.Unmarshal(Val, Data); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001013 logger.Errorw("Failed to unmarshal", log.Fields{"error": err})
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001014 return err
1015 }
1016 }
1017 }
1018 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001019}
1020
npujarec5762e2020-01-01 14:08:48 +05301021func (PONRMgr *PONResourceManager) RemoveFlowIDInfo(ctx context.Context, IntfONUID string, FlowID uint32) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001022 /*
1023 Get flow_id details configured for the ONU.
1024 :param pon_intf_onu_id: reference of PON interface id and onu id
1025 :param flow_id: Flow Id reference
1026 */
1027 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001028
npujarec5762e2020-01-01 14:08:48 +05301029 if err := PONRMgr.KVStore.Delete(ctx, Path); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001030 logger.Errorf("Falied to remove resource %s", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001031 return false
1032 }
1033 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001034}
1035
npujarec5762e2020-01-01 14:08:48 +05301036func (PONRMgr *PONResourceManager) UpdateAllocIdsForOnu(ctx context.Context, IntfONUID string, AllocIDs []uint32) error {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001037 /*
1038 Update currently configured alloc ids for given pon_intf_onu_id
1039 :param pon_intf_onu_id: reference of PON interface id and onu id
1040 :param alloc_ids: list of alloc ids
1041 */
1042 var Value []byte
1043 var err error
1044 Path := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
1045 Value, err = json.Marshal(AllocIDs)
1046 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001047 logger.Error("failed to Marshal")
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001048 return err
1049 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001050
npujarec5762e2020-01-01 14:08:48 +05301051 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001052 logger.Errorf("Failed to update resource %s", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001053 return err
1054 }
1055 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001056}
1057
npujarec5762e2020-01-01 14:08:48 +05301058func (PONRMgr *PONResourceManager) UpdateGEMPortIDsForOnu(ctx context.Context, IntfONUID string, GEMPortIDs []uint32) error {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001059 /*
1060 Update currently configured gemport ids for given pon_intf_onu_id
1061 :param pon_intf_onu_id: reference of PON interface id and onu id
1062 :param gemport_ids: list of gem port ids
1063 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001064
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001065 var Value []byte
1066 var err error
1067 Path := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
Scott Baker24f83e22020-03-30 16:14:28 -07001068 logger.Debugf("Updating gemport ids for %s", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001069 Value, err = json.Marshal(GEMPortIDs)
1070 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001071 logger.Error("failed to Marshal")
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001072 return err
1073 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001074
npujarec5762e2020-01-01 14:08:48 +05301075 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001076 logger.Errorf("Failed to update resource %s", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001077 return err
1078 }
1079 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001080}
1081
1082func checkForFlowIDInList(FlowIDList []uint32, FlowID uint32) (bool, uint32) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001083 /*
1084 Check for a flow id in a given list of flow IDs.
1085 :param FLowIDList: List of Flow IDs
1086 :param FlowID: Flowd to check in the list
1087 : return true and the index if present false otherwise.
1088 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001089
Rohan Agrawal02f784d2020-02-14 09:34:02 +00001090 for idx := range FlowIDList {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001091 if FlowID == FlowIDList[idx] {
1092 return true, uint32(idx)
1093 }
1094 }
1095 return false, 0
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001096}
1097
npujarec5762e2020-01-01 14:08:48 +05301098func (PONRMgr *PONResourceManager) UpdateFlowIDForOnu(ctx context.Context, IntfONUID string, FlowID uint32, Add bool) error {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001099 /*
1100 Update the flow_id list of the ONU (add or remove flow_id from the list)
1101 :param pon_intf_onu_id: reference of PON interface id and onu id
1102 :param flow_id: flow ID
1103 :param add: Boolean flag to indicate whether the flow_id should be
1104 added or removed from the list. Defaults to adding the flow.
1105 */
1106 var Value []byte
1107 var err error
1108 var RetVal bool
1109 var IDx uint32
1110 Path := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
npujarec5762e2020-01-01 14:08:48 +05301111 FlowIDs := PONRMgr.GetCurrentFlowIDsForOnu(ctx, IntfONUID)
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001112
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001113 if Add {
Rohan Agrawal02f784d2020-02-14 09:34:02 +00001114 if RetVal, _ = checkForFlowIDInList(FlowIDs, FlowID); RetVal {
1115 return nil
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001116 }
1117 FlowIDs = append(FlowIDs, FlowID)
1118 } else {
Rohan Agrawal02f784d2020-02-14 09:34:02 +00001119 if RetVal, IDx = checkForFlowIDInList(FlowIDs, FlowID); !RetVal {
1120 return nil
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001121 }
1122 // delete the index and shift
1123 FlowIDs = append(FlowIDs[:IDx], FlowIDs[IDx+1:]...)
1124 }
1125 Value, err = json.Marshal(FlowIDs)
1126 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001127 logger.Error("Failed to Marshal")
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001128 return err
1129 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001130
npujarec5762e2020-01-01 14:08:48 +05301131 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001132 logger.Errorf("Failed to update resource %s", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001133 return err
1134 }
1135 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001136}
1137
npujarec5762e2020-01-01 14:08:48 +05301138func (PONRMgr *PONResourceManager) UpdateFlowIDInfoForOnu(ctx context.Context, IntfONUID string, FlowID uint32, FlowData interface{}) error {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001139 /*
1140 Update any metadata associated with the flow_id. The flow_data could be json
1141 or any of other data structure. The resource manager doesnt care
1142 :param pon_intf_onu_id: reference of PON interface id and onu id
1143 :param flow_id: Flow ID
1144 :param flow_data: Flow data blob
1145 */
1146 var Value []byte
1147 var err error
1148 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
1149 Value, err = json.Marshal(FlowData)
1150 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001151 logger.Error("failed to Marshal")
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001152 return err
1153 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001154
npujarec5762e2020-01-01 14:08:48 +05301155 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001156 logger.Errorf("Failed to update resource %s", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001157 return err
1158 }
1159 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001160}
1161
1162func (PONRMgr *PONResourceManager) GenerateNextID(Resource map[string]interface{}) (uint32, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001163 /*
1164 Generate unique id having OFFSET as start
1165 :param resource: resource used to generate ID
1166 :return uint32: generated id
1167 */
1168 ByteArray, err := ToByte(Resource[POOL])
1169 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001170 logger.Error("Failed to convert resource to byte array")
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001171 return 0, err
1172 }
1173 Data := bitmap.TSFromData(ByteArray, false)
1174 if Data == nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001175 logger.Error("Failed to get data from byte array")
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001176 return 0, errors.New("Failed to get data from byte array")
1177 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001178
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001179 Len := Data.Len()
1180 var Idx int
1181 for Idx = 0; Idx < Len; Idx++ {
Rohan Agrawal02f784d2020-02-14 09:34:02 +00001182 if !Data.Get(Idx) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001183 break
1184 }
1185 }
1186 Data.Set(Idx, true)
1187 res := uint32(Resource[START_IDX].(float64))
1188 Resource[POOL] = Data.Data(false)
Scott Baker24f83e22020-03-30 16:14:28 -07001189 logger.Debugf("Generated ID for %d", (uint32(Idx) + res))
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001190 return (uint32(Idx) + res), err
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001191}
1192
1193func (PONRMgr *PONResourceManager) ReleaseID(Resource map[string]interface{}, Id uint32) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001194 /*
1195 Release unique id having OFFSET as start index.
1196 :param resource: resource used to release ID
1197 :param unique_id: id need to be released
1198 */
1199 ByteArray, err := ToByte(Resource[POOL])
1200 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001201 logger.Error("Failed to convert resource to byte array")
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001202 return false
1203 }
1204 Data := bitmap.TSFromData(ByteArray, false)
1205 if Data == nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001206 logger.Error("Failed to get resource pool")
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001207 return false
1208 }
Rohan Agrawal02f784d2020-02-14 09:34:02 +00001209 Idx := Id - uint32(Resource[START_IDX].(float64))
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001210 Data.Set(int(Idx), false)
1211 Resource[POOL] = Data.Data(false)
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001212
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001213 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001214}
1215
divyadesaid26f6b12020-03-19 06:30:28 +00001216/* Reserves a unique id in the specified resource pool.
1217:param Resource: resource used to reserve ID
1218:param Id: ID to be reserved
1219*/
1220func (PONRMgr *PONResourceManager) reserveID(TSData *bitmap.Threadsafe, StartIndex uint32, Id uint32) bool {
1221 Data := bitmap.TSFromData(TSData.Data(false), false)
1222 if Data == nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001223 logger.Error("Failed to get resource pool")
divyadesaid26f6b12020-03-19 06:30:28 +00001224 return false
1225 }
1226 Idx := Id - StartIndex
1227 Data.Set(int(Idx), true)
1228 return true
1229}
1230
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001231func (PONRMgr *PONResourceManager) GetTechnology() string {
1232 return PONRMgr.Technology
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001233}
1234
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001235func (PONRMgr *PONResourceManager) GetResourceTypeAllocID() string {
1236 return ALLOC_ID
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001237}
1238
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001239func (PONRMgr *PONResourceManager) GetResourceTypeGemPortID() string {
1240 return GEMPORT_ID
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001241}
1242
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001243// ToByte converts an interface value to a []byte. The interface should either be of
1244// a string type or []byte. Otherwise, an error is returned.
1245func ToByte(value interface{}) ([]byte, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001246 switch t := value.(type) {
1247 case []byte:
1248 return value.([]byte), nil
1249 case string:
1250 return []byte(value.(string)), nil
1251 default:
1252 return nil, fmt.Errorf("unexpected-type-%T", t)
1253 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001254}
1255
1256// ToString converts an interface value to a string. The interface should either be of
1257// a string type or []byte. Otherwise, an error is returned.
1258func ToString(value interface{}) (string, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001259 switch t := value.(type) {
1260 case []byte:
1261 return string(value.([]byte)), nil
1262 case string:
1263 return value.(string), nil
1264 default:
1265 return "", fmt.Errorf("unexpected-type-%T", t)
1266 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001267}
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001268
npujarec5762e2020-01-01 14:08:48 +05301269func (PONRMgr *PONResourceManager) AddOnuGemInfo(ctx context.Context, intfID uint32, onuGemData interface{}) error {
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001270 /*
1271 Update onugem info map,
1272 :param pon_intf_id: reference of PON interface id
1273 :param onuegmdata: onugem info map
1274 */
1275 var Value []byte
1276 var err error
1277 Path := fmt.Sprintf(ONU_GEM_INFO_PATH, PONRMgr.DeviceID, intfID)
1278 Value, err = json.Marshal(onuGemData)
1279 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001280 logger.Error("failed to Marshal")
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001281 return err
1282 }
1283
npujarec5762e2020-01-01 14:08:48 +05301284 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001285 logger.Errorf("Failed to update resource %s", Path)
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001286 return err
1287 }
1288 return err
1289}
1290
npujarec5762e2020-01-01 14:08:48 +05301291func (PONRMgr *PONResourceManager) GetOnuGemInfo(ctx context.Context, IntfId uint32, onuGemInfo interface{}) error {
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001292 /*
1293 Get onugeminfo map from kvstore
1294 :param intfid: refremce pon intfid
1295 :param onuGemInfo: onugem info to return from kv strore.
1296 */
1297 var Val []byte
1298
1299 path := fmt.Sprintf(ONU_GEM_INFO_PATH, PONRMgr.DeviceID, IntfId)
npujarec5762e2020-01-01 14:08:48 +05301300 value, err := PONRMgr.KVStore.Get(ctx, path)
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001301 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001302 logger.Errorw("Failed to get from kv store", log.Fields{"path": path})
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001303 return err
1304 } else if value == nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001305 logger.Debug("No onuinfo for path", log.Fields{"path": path})
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001306 return nil // returning nil as this could happen if there are no onus for the interface yet
1307 }
1308 if Val, err = kvstore.ToByte(value.Value); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001309 logger.Error("Failed to convert to byte array")
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001310 return err
1311 }
1312
1313 if err = json.Unmarshal(Val, &onuGemInfo); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001314 logger.Error("Failed to unmarshall")
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001315 return err
1316 }
Scott Baker24f83e22020-03-30 16:14:28 -07001317 logger.Debugw("found onuinfo from path", log.Fields{"path": path, "onuinfo": onuGemInfo})
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001318 return err
1319}
1320
npujarec5762e2020-01-01 14:08:48 +05301321func (PONRMgr *PONResourceManager) DelOnuGemInfoForIntf(ctx context.Context, intfId uint32) error {
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001322 /*
1323 delete onugem info for an interface from kvstore
1324 :param intfid: refremce pon intfid
1325 */
1326
1327 path := fmt.Sprintf(ONU_GEM_INFO_PATH, PONRMgr.DeviceID, intfId)
npujarec5762e2020-01-01 14:08:48 +05301328 if err := PONRMgr.KVStore.Delete(ctx, path); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001329 logger.Errorf("Falied to remove resource %s", path)
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001330 return err
1331 }
1332 return nil
1333}