blob: 4cccb845116bfcb3a0e4e93d8e848a4706a46700 [file] [log] [blame]
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001/*
2 * Copyright 2019-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package ponresourcemanager
18
19import (
npujarec5762e2020-01-01 14:08:48 +053020 "context"
Matt Jeanneret384d8c92019-05-06 14:27:31 -040021 "encoding/base64"
22 "encoding/json"
23 "errors"
24 "fmt"
25 "strconv"
Neha Sharmacc656962020-04-14 14:26:11 +000026 "time"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040027
Esin Karamanccb714b2019-11-29 15:02:06 +000028 bitmap "github.com/boljen/go-bitmap"
29 "github.com/opencord/voltha-lib-go/v3/pkg/db"
30 "github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore"
31 "github.com/opencord/voltha-lib-go/v3/pkg/log"
32 tp "github.com/opencord/voltha-lib-go/v3/pkg/techprofile"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040033)
34
35const (
Matt Jeanneret384d8c92019-05-06 14:27:31 -040036 //Constants to identify resource pool
37 UNI_ID = "UNI_ID"
38 ONU_ID = "ONU_ID"
39 ALLOC_ID = "ALLOC_ID"
40 GEMPORT_ID = "GEMPORT_ID"
41 FLOW_ID = "FLOW_ID"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040042
Matt Jeanneret384d8c92019-05-06 14:27:31 -040043 //Constants for passing command line arugments
44 OLT_MODEL_ARG = "--olt_model"
45 PATH_PREFIX = "service/voltha/resource_manager/{%s}"
divyadesaid26f6b12020-03-19 06:30:28 +000046
47 /*The path under which configuration data is stored is defined as technology/device agnostic.
48 That means the path does not include any specific technology/device variable. Using technology/device
49 agnostic path also makes northbound applications, that need to write to this path,
50 technology/device agnostic.
51
52 Default kv client of PonResourceManager reads from/writes to PATH_PREFIX defined above.
53 That is why, an additional kv client (named KVStoreForConfig) is defined to read from the config path.
54 */
55 PATH_PREFIX_FOR_CONFIG = "service/voltha/resource_manager/config"
Matt Jeanneret384d8c92019-05-06 14:27:31 -040056 /*The resource ranges for a given device model should be placed
57 at 'resource_manager/<technology>/resource_ranges/<olt_model_type>'
58 path on the KV store.
59 If Resource Range parameters are to be read from the external KV store,
60 they are expected to be stored in the following format.
61 Note: All parameters are MANDATORY for now.
62 constants used as keys to reference the resource range parameters from
63 and external KV store.
64 */
65 UNI_ID_START_IDX = "uni_id_start"
66 UNI_ID_END_IDX = "uni_id_end"
67 ONU_ID_START_IDX = "onu_id_start"
68 ONU_ID_END_IDX = "onu_id_end"
69 ONU_ID_SHARED_IDX = "onu_id_shared"
70 ALLOC_ID_START_IDX = "alloc_id_start"
71 ALLOC_ID_END_IDX = "alloc_id_end"
72 ALLOC_ID_SHARED_IDX = "alloc_id_shared"
73 GEMPORT_ID_START_IDX = "gemport_id_start"
74 GEMPORT_ID_END_IDX = "gemport_id_end"
75 GEMPORT_ID_SHARED_IDX = "gemport_id_shared"
76 FLOW_ID_START_IDX = "flow_id_start"
77 FLOW_ID_END_IDX = "flow_id_end"
78 FLOW_ID_SHARED_IDX = "flow_id_shared"
79 NUM_OF_PON_PORT = "pon_ports"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040080
Matt Jeanneret384d8c92019-05-06 14:27:31 -040081 /*
82 The KV store backend is initialized with a path prefix and we need to
83 provide only the suffix.
84 */
85 PON_RESOURCE_RANGE_CONFIG_PATH = "resource_ranges/%s"
Matt Jeanneretcab955f2019-04-10 15:45:57 -040086
Matt Jeanneret384d8c92019-05-06 14:27:31 -040087 //resource path suffix
88 //Path on the KV store for storing alloc id ranges and resource pool for a given interface
89 //Format: <device_id>/alloc_id_pool/<pon_intf_id>
90 ALLOC_ID_POOL_PATH = "{%s}/alloc_id_pool/{%d}"
91 //Path on the KV store for storing gemport id ranges and resource pool for a given interface
92 //Format: <device_id>/gemport_id_pool/<pon_intf_id>
93 GEMPORT_ID_POOL_PATH = "{%s}/gemport_id_pool/{%d}"
94 //Path on the KV store for storing onu id ranges and resource pool for a given interface
95 //Format: <device_id>/onu_id_pool/<pon_intf_id>
96 ONU_ID_POOL_PATH = "{%s}/onu_id_pool/{%d}"
97 //Path on the KV store for storing flow id ranges and resource pool for a given interface
98 //Format: <device_id>/flow_id_pool/<pon_intf_id>
99 FLOW_ID_POOL_PATH = "{%s}/flow_id_pool/{%d}"
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400100
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400101 //Path on the KV store for storing list of alloc IDs for a given ONU
102 //Format: <device_id>/<(pon_intf_id, onu_id)>/alloc_ids
103 ALLOC_ID_RESOURCE_MAP_PATH = "{%s}/{%s}/alloc_ids"
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400104
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400105 //Path on the KV store for storing list of gemport IDs for a given ONU
106 //Format: <device_id>/<(pon_intf_id, onu_id)>/gemport_ids
107 GEMPORT_ID_RESOURCE_MAP_PATH = "{%s}/{%s}/gemport_ids"
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400108
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400109 //Path on the KV store for storing list of Flow IDs for a given ONU
110 //Format: <device_id>/<(pon_intf_id, onu_id)>/flow_ids
111 FLOW_ID_RESOURCE_MAP_PATH = "{%s}/{%s}/flow_ids"
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400112
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400113 //Flow Id info: Use to store more metadata associated with the flow_id
114 //Format: <device_id>/<(pon_intf_id, onu_id)>/flow_id_info/<flow_id>
115 FLOW_ID_INFO_PATH = "{%s}/{%s}/flow_id_info/{%d}"
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400116
Scott Bakerc6e54cb2019-11-04 09:31:25 -0800117 //path on the kvstore to store onugem info map
118 //format: <device-id>/onu_gem_info/<intfid>
119 ONU_GEM_INFO_PATH = "{%s}/onu_gem_info/{%d}" // onu_gem/<(intfid)>
120
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400121 //Constants for internal usage.
122 PON_INTF_ID = "pon_intf_id"
123 START_IDX = "start_idx"
124 END_IDX = "end_idx"
125 POOL = "pool"
126 NUM_OF_PON_INTF = 16
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400127
Neha Sharmacc656962020-04-14 14:26:11 +0000128 KVSTORE_RETRY_TIMEOUT = 5 * time.Second
divyadesaid26f6b12020-03-19 06:30:28 +0000129 //Path on the KV store for storing reserved gem ports
130 //Format: reserved_gemport_ids
131 RESERVED_GEMPORT_IDS_PATH = "reserved_gemport_ids"
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400132)
133
134//type ResourceTypeIndex string
135//type ResourceType string
136
137type PONResourceManager struct {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400138 //Implements APIs to initialize/allocate/release alloc/gemport/onu IDs.
divyadesaid26f6b12020-03-19 06:30:28 +0000139 Technology string
140 DeviceType string
141 DeviceID string
142 Backend string // ETCD, or consul
143 Host string // host ip of the KV store
144 Port int // port number for the KV store
145 OLTModel string
146 KVStore *db.Backend
147 KVStoreForConfig *db.Backend
148 TechProfileMgr tp.TechProfileIf // create object of *tp.TechProfileMgr
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400149
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400150 // Below attribute, pon_resource_ranges, should be initialized
151 // by reading from KV store.
152 PonResourceRanges map[string]interface{}
153 SharedResourceMgrs map[string]*PONResourceManager
154 SharedIdxByType map[string]string
155 IntfIDs []uint32 // list of pon interface IDs
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400156 Globalorlocal string
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400157}
158
Neha Sharmacc656962020-04-14 14:26:11 +0000159func newKVClient(storeType string, address string, timeout time.Duration) (kvstore.Client, error) {
Scott Baker24f83e22020-03-30 16:14:28 -0700160 logger.Infow("kv-store-type", log.Fields{"store": storeType})
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400161 switch storeType {
162 case "consul":
163 return kvstore.NewConsulClient(address, timeout)
164 case "etcd":
Scott Bakered4a8e72020-04-17 11:10:20 -0700165 return kvstore.NewEtcdClient(address, timeout, log.WarnLevel)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400166 }
167 return nil, errors.New("unsupported-kv-store")
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400168}
169
divyadesaid26f6b12020-03-19 06:30:28 +0000170func SetKVClient(Technology string, Backend string, Host string, Port int, configClient bool) *db.Backend {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400171 addr := Host + ":" + strconv.Itoa(Port)
172 // TODO : Make sure direct call to NewBackend is working fine with backend , currently there is some
173 // issue between kv store and backend , core is not calling NewBackend directly
174 kvClient, err := newKVClient(Backend, addr, KVSTORE_RETRY_TIMEOUT)
175 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700176 logger.Fatalw("Failed to init KV client\n", log.Fields{"err": err})
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400177 return nil
178 }
divyadesaid26f6b12020-03-19 06:30:28 +0000179
180 var pathPrefix string
181 if configClient {
182 pathPrefix = PATH_PREFIX_FOR_CONFIG
183 } else {
184 pathPrefix = fmt.Sprintf(PATH_PREFIX, Technology)
185 }
186
sbarbaria8910ba2019-11-05 10:12:23 -0500187 kvbackend := &db.Backend{
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400188 Client: kvClient,
189 StoreType: Backend,
190 Host: Host,
191 Port: Port,
192 Timeout: KVSTORE_RETRY_TIMEOUT,
divyadesaid26f6b12020-03-19 06:30:28 +0000193 PathPrefix: pathPrefix}
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400194
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400195 return kvbackend
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400196}
197
198// NewPONResourceManager creates a new PON resource manager.
199func NewPONResourceManager(Technology string, DeviceType string, DeviceID string, Backend string, Host string, Port int) (*PONResourceManager, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400200 var PONMgr PONResourceManager
201 PONMgr.Technology = Technology
202 PONMgr.DeviceType = DeviceType
203 PONMgr.DeviceID = DeviceID
204 PONMgr.Backend = Backend
205 PONMgr.Host = Host
206 PONMgr.Port = Port
divyadesaid26f6b12020-03-19 06:30:28 +0000207 PONMgr.KVStore = SetKVClient(Technology, Backend, Host, Port, false)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400208 if PONMgr.KVStore == nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700209 logger.Error("KV Client initilization failed")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400210 return nil, errors.New("Failed to init KV client")
211 }
divyadesaid26f6b12020-03-19 06:30:28 +0000212 // init kv client to read from the config path
213 PONMgr.KVStoreForConfig = SetKVClient(Technology, Backend, Host, Port, true)
214 if PONMgr.KVStoreForConfig == nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700215 logger.Error("KV Config Client initilization failed")
divyadesaid26f6b12020-03-19 06:30:28 +0000216 return nil, errors.New("Failed to init KV Config client")
217 }
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400218 // Initialize techprofile for this technology
Matt Jeannereta93dbed2019-05-17 12:40:05 -0400219 if PONMgr.TechProfileMgr, _ = tp.NewTechProfile(&PONMgr, Backend, Host, Port); PONMgr.TechProfileMgr == nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700220 logger.Error("Techprofile initialization failed")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400221 return nil, errors.New("Failed to init tech profile")
222 }
223 PONMgr.PonResourceRanges = make(map[string]interface{})
224 PONMgr.SharedResourceMgrs = make(map[string]*PONResourceManager)
225 PONMgr.SharedIdxByType = make(map[string]string)
226 PONMgr.SharedIdxByType[ONU_ID] = ONU_ID_SHARED_IDX
227 PONMgr.SharedIdxByType[ALLOC_ID] = ALLOC_ID_SHARED_IDX
228 PONMgr.SharedIdxByType[GEMPORT_ID] = GEMPORT_ID_SHARED_IDX
229 PONMgr.SharedIdxByType[FLOW_ID] = FLOW_ID_SHARED_IDX
230 PONMgr.IntfIDs = make([]uint32, NUM_OF_PON_INTF)
231 PONMgr.OLTModel = DeviceType
232 return &PONMgr, nil
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400233}
234
235/*
236 Initialize PON resource ranges with config fetched from kv store.
237 return boolean: True if PON resource ranges initialized else false
238 Try to initialize the PON Resource Ranges from KV store based on the
239 OLT model key, if available
240*/
241
npujarec5762e2020-01-01 14:08:48 +0530242func (PONRMgr *PONResourceManager) InitResourceRangesFromKVStore(ctx context.Context) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400243 //Initialize PON resource ranges with config fetched from kv store.
244 //:return boolean: True if PON resource ranges initialized else false
245 // Try to initialize the PON Resource Ranges from KV store based on the
246 // OLT model key, if available
247 if PONRMgr.OLTModel == "" {
Scott Baker24f83e22020-03-30 16:14:28 -0700248 logger.Error("Failed to get OLT model")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400249 return false
250 }
251 Path := fmt.Sprintf(PON_RESOURCE_RANGE_CONFIG_PATH, PONRMgr.OLTModel)
252 //get resource from kv store
npujarec5762e2020-01-01 14:08:48 +0530253 Result, err := PONRMgr.KVStore.Get(ctx, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400254 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700255 logger.Debugf("Error in fetching resource %s from KV strore", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400256 return false
257 }
258 if Result == nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700259 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 -0400260 return false
261 }
262 //update internal ranges from kv ranges. If there are missing
263 // values in the KV profile, continue to use the defaults
264 Value, err := ToByte(Result.Value)
265 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700266 logger.Error("Failed to convert kvpair to byte string")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400267 return false
268 }
269 if err := json.Unmarshal(Value, &PONRMgr.PonResourceRanges); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700270 logger.Error("Failed to Unmarshal json byte")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400271 return false
272 }
Scott Baker24f83e22020-03-30 16:14:28 -0700273 logger.Debug("Init resource ranges from kvstore success")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400274 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400275}
276
277func (PONRMgr *PONResourceManager) UpdateRanges(StartIDx string, StartID uint32, EndIDx string, EndID uint32,
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400278 SharedIDx string, SharedPoolID uint32, RMgr *PONResourceManager) {
279 /*
280 Update the ranges for all reosurce type in the intermnal maps
281 param: resource type start index
282 param: start ID
283 param: resource type end index
284 param: end ID
285 param: resource type shared index
286 param: shared pool id
287 param: global resource manager
288 */
Scott Baker24f83e22020-03-30 16:14:28 -0700289 logger.Debugf("update ranges for %s, %d", StartIDx, StartID)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400290
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400291 if StartID != 0 {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400292 if (PONRMgr.PonResourceRanges[StartIDx] == nil) || (PONRMgr.PonResourceRanges[StartIDx].(uint32) < StartID) {
293 PONRMgr.PonResourceRanges[StartIDx] = StartID
294 }
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400295 }
296 if EndID != 0 {
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400297 if (PONRMgr.PonResourceRanges[EndIDx] == nil) || (PONRMgr.PonResourceRanges[EndIDx].(uint32) > EndID) {
298 PONRMgr.PonResourceRanges[EndIDx] = EndID
299 }
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400300 }
301 //if SharedPoolID != 0 {
302 PONRMgr.PonResourceRanges[SharedIDx] = SharedPoolID
303 //}
304 if RMgr != nil {
305 PONRMgr.SharedResourceMgrs[SharedIDx] = RMgr
306 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400307}
308
309func (PONRMgr *PONResourceManager) InitDefaultPONResourceRanges(ONUIDStart uint32,
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400310 ONUIDEnd uint32,
311 ONUIDSharedPoolID uint32,
312 AllocIDStart uint32,
313 AllocIDEnd uint32,
314 AllocIDSharedPoolID uint32,
315 GEMPortIDStart uint32,
316 GEMPortIDEnd uint32,
317 GEMPortIDSharedPoolID uint32,
318 FlowIDStart uint32,
319 FlowIDEnd uint32,
320 FlowIDSharedPoolID uint32,
321 UNIIDStart uint32,
322 UNIIDEnd uint32,
323 NoOfPONPorts uint32,
324 IntfIDs []uint32) bool {
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400325
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400326 /*Initialize default PON resource ranges
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400327
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400328 :param onu_id_start_idx: onu id start index
329 :param onu_id_end_idx: onu id end index
330 :param onu_id_shared_pool_id: pool idx for id shared by all intfs or None for no sharing
331 :param alloc_id_start_idx: alloc id start index
332 :param alloc_id_end_idx: alloc id end index
333 :param alloc_id_shared_pool_id: pool idx for alloc id shared by all intfs or None for no sharing
334 :param gemport_id_start_idx: gemport id start index
335 :param gemport_id_end_idx: gemport id end index
336 :param gemport_id_shared_pool_id: pool idx for gemport id shared by all intfs or None for no sharing
337 :param flow_id_start_idx: flow id start index
338 :param flow_id_end_idx: flow id end index
339 :param flow_id_shared_pool_id: pool idx for flow id shared by all intfs or None for no sharing
340 :param num_of_pon_ports: number of PON ports
341 :param intf_ids: interfaces serviced by this manager
342 */
343 PONRMgr.UpdateRanges(ONU_ID_START_IDX, ONUIDStart, ONU_ID_END_IDX, ONUIDEnd, ONU_ID_SHARED_IDX, ONUIDSharedPoolID, nil)
344 PONRMgr.UpdateRanges(ALLOC_ID_START_IDX, AllocIDStart, ALLOC_ID_END_IDX, AllocIDEnd, ALLOC_ID_SHARED_IDX, AllocIDSharedPoolID, nil)
345 PONRMgr.UpdateRanges(GEMPORT_ID_START_IDX, GEMPortIDStart, GEMPORT_ID_END_IDX, GEMPortIDEnd, GEMPORT_ID_SHARED_IDX, GEMPortIDSharedPoolID, nil)
346 PONRMgr.UpdateRanges(FLOW_ID_START_IDX, FlowIDStart, FLOW_ID_END_IDX, FlowIDEnd, FLOW_ID_SHARED_IDX, FlowIDSharedPoolID, nil)
347 PONRMgr.UpdateRanges(UNI_ID_START_IDX, UNIIDStart, UNI_ID_END_IDX, UNIIDEnd, "", 0, nil)
Scott Baker24f83e22020-03-30 16:14:28 -0700348 logger.Debug("Initialize default range values")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400349 var i uint32
350 if IntfIDs == nil {
351 for i = 0; i < NoOfPONPorts; i++ {
352 PONRMgr.IntfIDs = append(PONRMgr.IntfIDs, i)
353 }
354 } else {
355 PONRMgr.IntfIDs = IntfIDs
356 }
357 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400358}
359
npujarec5762e2020-01-01 14:08:48 +0530360func (PONRMgr *PONResourceManager) InitDeviceResourcePool(ctx context.Context) error {
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400361
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400362 //Initialize resource pool for all PON ports.
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400363
Scott Baker24f83e22020-03-30 16:14:28 -0700364 logger.Debug("Init resource ranges")
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400365
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400366 var err error
367 for _, Intf := range PONRMgr.IntfIDs {
368 SharedPoolID := PONRMgr.PonResourceRanges[ONU_ID_SHARED_IDX].(uint32)
369 if SharedPoolID != 0 {
370 Intf = SharedPoolID
371 }
npujarec5762e2020-01-01 14:08:48 +0530372 if err = PONRMgr.InitResourceIDPool(ctx, Intf, ONU_ID,
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400373 PONRMgr.PonResourceRanges[ONU_ID_START_IDX].(uint32),
374 PONRMgr.PonResourceRanges[ONU_ID_END_IDX].(uint32)); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700375 logger.Error("Failed to init ONU ID resource pool")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400376 return err
377 }
378 if SharedPoolID != 0 {
379 break
380 }
381 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400382
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400383 for _, Intf := range PONRMgr.IntfIDs {
384 SharedPoolID := PONRMgr.PonResourceRanges[ALLOC_ID_SHARED_IDX].(uint32)
385 if SharedPoolID != 0 {
386 Intf = SharedPoolID
387 }
npujarec5762e2020-01-01 14:08:48 +0530388 if err = PONRMgr.InitResourceIDPool(ctx, Intf, ALLOC_ID,
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400389 PONRMgr.PonResourceRanges[ALLOC_ID_START_IDX].(uint32),
390 PONRMgr.PonResourceRanges[ALLOC_ID_END_IDX].(uint32)); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700391 logger.Error("Failed to init ALLOC ID resource pool ")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400392 return err
393 }
394 if SharedPoolID != 0 {
395 break
396 }
397 }
398 for _, Intf := range PONRMgr.IntfIDs {
399 SharedPoolID := PONRMgr.PonResourceRanges[GEMPORT_ID_SHARED_IDX].(uint32)
400 if SharedPoolID != 0 {
401 Intf = SharedPoolID
402 }
npujarec5762e2020-01-01 14:08:48 +0530403 if err = PONRMgr.InitResourceIDPool(ctx, Intf, GEMPORT_ID,
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400404 PONRMgr.PonResourceRanges[GEMPORT_ID_START_IDX].(uint32),
405 PONRMgr.PonResourceRanges[GEMPORT_ID_END_IDX].(uint32)); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700406 logger.Error("Failed to init GEMPORT ID resource pool")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400407 return err
408 }
409 if SharedPoolID != 0 {
410 break
411 }
412 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400413
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400414 for _, Intf := range PONRMgr.IntfIDs {
415 SharedPoolID := PONRMgr.PonResourceRanges[FLOW_ID_SHARED_IDX].(uint32)
416 if SharedPoolID != 0 {
417 Intf = SharedPoolID
418 }
npujarec5762e2020-01-01 14:08:48 +0530419 if err = PONRMgr.InitResourceIDPool(ctx, Intf, FLOW_ID,
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400420 PONRMgr.PonResourceRanges[FLOW_ID_START_IDX].(uint32),
421 PONRMgr.PonResourceRanges[FLOW_ID_END_IDX].(uint32)); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700422 logger.Error("Failed to init FLOW ID resource pool")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400423 return err
424 }
425 if SharedPoolID != 0 {
426 break
427 }
428 }
429 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400430}
431
npujarec5762e2020-01-01 14:08:48 +0530432func (PONRMgr *PONResourceManager) ClearDeviceResourcePool(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -0400433
434 //Clear resource pool for all PON ports.
435
Scott Baker24f83e22020-03-30 16:14:28 -0700436 logger.Debug("Clear resource ranges")
Devmalya Paul495b94a2019-08-27 19:42:00 -0400437
438 for _, Intf := range PONRMgr.IntfIDs {
439 SharedPoolID := PONRMgr.PonResourceRanges[ONU_ID_SHARED_IDX].(uint32)
440 if SharedPoolID != 0 {
441 Intf = SharedPoolID
442 }
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000443 if status := PONRMgr.ClearResourceIDPool(ctx, Intf, ONU_ID); !status {
Scott Baker24f83e22020-03-30 16:14:28 -0700444 logger.Error("Failed to clear ONU ID resource pool")
Devmalya Paul495b94a2019-08-27 19:42:00 -0400445 return errors.New("Failed to clear ONU ID resource pool")
446 }
447 if SharedPoolID != 0 {
448 break
449 }
450 }
451
452 for _, Intf := range PONRMgr.IntfIDs {
453 SharedPoolID := PONRMgr.PonResourceRanges[ALLOC_ID_SHARED_IDX].(uint32)
454 if SharedPoolID != 0 {
455 Intf = SharedPoolID
456 }
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000457 if status := PONRMgr.ClearResourceIDPool(ctx, Intf, ALLOC_ID); !status {
Scott Baker24f83e22020-03-30 16:14:28 -0700458 logger.Error("Failed to clear ALLOC ID resource pool ")
Devmalya Paul495b94a2019-08-27 19:42:00 -0400459 return errors.New("Failed to clear ALLOC ID resource pool")
460 }
461 if SharedPoolID != 0 {
462 break
463 }
464 }
465 for _, Intf := range PONRMgr.IntfIDs {
466 SharedPoolID := PONRMgr.PonResourceRanges[GEMPORT_ID_SHARED_IDX].(uint32)
467 if SharedPoolID != 0 {
468 Intf = SharedPoolID
469 }
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000470 if status := PONRMgr.ClearResourceIDPool(ctx, Intf, GEMPORT_ID); !status {
Scott Baker24f83e22020-03-30 16:14:28 -0700471 logger.Error("Failed to clear GEMPORT ID resource pool")
Devmalya Paul495b94a2019-08-27 19:42:00 -0400472 return errors.New("Failed to clear GEMPORT ID resource pool")
473 }
474 if SharedPoolID != 0 {
475 break
476 }
477 }
478
479 for _, Intf := range PONRMgr.IntfIDs {
480 SharedPoolID := PONRMgr.PonResourceRanges[FLOW_ID_SHARED_IDX].(uint32)
481 if SharedPoolID != 0 {
482 Intf = SharedPoolID
483 }
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000484 if status := PONRMgr.ClearResourceIDPool(ctx, Intf, FLOW_ID); !status {
Scott Baker24f83e22020-03-30 16:14:28 -0700485 logger.Error("Failed to clear FLOW ID resource pool")
Devmalya Paul495b94a2019-08-27 19:42:00 -0400486 return errors.New("Failed to clear FLOW ID resource pool")
487 }
488 if SharedPoolID != 0 {
489 break
490 }
491 }
492 return nil
493}
494
npujarec5762e2020-01-01 14:08:48 +0530495func (PONRMgr *PONResourceManager) InitResourceIDPool(ctx context.Context, Intf uint32, ResourceType string, StartID uint32, EndID uint32) error {
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400496
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400497 /*Initialize Resource ID pool for a given Resource Type on a given PON Port
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400498
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400499 :param pon_intf_id: OLT PON interface id
500 :param resource_type: String to identify type of resource
501 :param start_idx: start index for onu id pool
502 :param end_idx: end index for onu id pool
503 :return boolean: True if resource id pool initialized else false
504 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400505
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400506 // delegate to the master instance if sharing enabled across instances
507 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
508 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
npujarec5762e2020-01-01 14:08:48 +0530509 return SharedResourceMgr.InitResourceIDPool(ctx, Intf, ResourceType, StartID, EndID)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400510 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400511
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400512 Path := PONRMgr.GetPath(Intf, ResourceType)
513 if Path == "" {
Scott Baker24f83e22020-03-30 16:14:28 -0700514 logger.Errorf("Failed to get path for resource type %s", ResourceType)
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000515 return fmt.Errorf("Failed to get path for resource type %s", ResourceType)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400516 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400517
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400518 //In case of adapter reboot and reconciliation resource in kv store
519 //checked for its presence if not kv store update happens
npujarec5762e2020-01-01 14:08:48 +0530520 Res, err := PONRMgr.GetResource(ctx, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400521 if (err == nil) && (Res != nil) {
Scott Baker24f83e22020-03-30 16:14:28 -0700522 logger.Debugf("Resource %s already present in store ", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400523 return nil
524 } else {
divyadesaid26f6b12020-03-19 06:30:28 +0000525 var excluded []uint32
526 if ResourceType == GEMPORT_ID {
527 //get gem port ids defined in the KV store, if any, and exclude them from the gem port id pool
528 if reservedGemPortIds, defined := PONRMgr.getReservedGemPortIdsFromKVStore(ctx); defined {
529 excluded = reservedGemPortIds
Scott Baker24f83e22020-03-30 16:14:28 -0700530 logger.Debugw("Excluding some ports from GEM port id pool", log.Fields{"excluded gem ports": excluded})
divyadesaid26f6b12020-03-19 06:30:28 +0000531 }
532 }
533 FormatResult, err := PONRMgr.FormatResource(Intf, StartID, EndID, excluded)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400534 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700535 logger.Errorf("Failed to format resource")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400536 return err
537 }
538 // Add resource as json in kv store.
npujarec5762e2020-01-01 14:08:48 +0530539 err = PONRMgr.KVStore.Put(ctx, Path, FormatResult)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400540 if err == nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700541 logger.Debug("Successfuly posted to kv store")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400542 return err
543 }
544 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400545
Scott Baker24f83e22020-03-30 16:14:28 -0700546 logger.Debug("Error initializing pool")
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400547
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400548 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400549}
550
divyadesaid26f6b12020-03-19 06:30:28 +0000551func (PONRMgr *PONResourceManager) getReservedGemPortIdsFromKVStore(ctx context.Context) ([]uint32, bool) {
552 var reservedGemPortIds []uint32
553 // read reserved gem ports from the config path
554 KvPair, err := PONRMgr.KVStoreForConfig.Get(ctx, RESERVED_GEMPORT_IDS_PATH)
555 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700556 logger.Errorw("Unable to get reserved GEM port ids from the kv store", log.Fields{"err": err})
divyadesaid26f6b12020-03-19 06:30:28 +0000557 return reservedGemPortIds, false
558 }
559 if KvPair == nil || KvPair.Value == nil {
560 //no reserved gem port defined in the store
561 return reservedGemPortIds, false
562 }
563 Val, err := kvstore.ToByte(KvPair.Value)
564 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700565 logger.Errorw("Failed to convert reserved gem port ids into byte array", log.Fields{"err": err})
divyadesaid26f6b12020-03-19 06:30:28 +0000566 return reservedGemPortIds, false
567 }
568 if err = json.Unmarshal(Val, &reservedGemPortIds); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700569 logger.Errorw("Failed to unmarshal reservedGemPortIds", log.Fields{"err": err})
divyadesaid26f6b12020-03-19 06:30:28 +0000570 return reservedGemPortIds, false
571 }
572 return reservedGemPortIds, true
573}
574
575func (PONRMgr *PONResourceManager) FormatResource(IntfID uint32, StartIDx uint32, EndIDx uint32,
576 Excluded []uint32) ([]byte, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400577 /*
578 Format resource as json.
579 :param pon_intf_id: OLT PON interface id
580 :param start_idx: start index for id pool
581 :param end_idx: end index for id pool
divyadesaid26f6b12020-03-19 06:30:28 +0000582 :Id values to be Excluded from the pool
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400583 :return dictionary: resource formatted as map
584 */
585 // Format resource as json to be stored in backend store
586 Resource := make(map[string]interface{})
587 Resource[PON_INTF_ID] = IntfID
588 Resource[START_IDX] = StartIDx
589 Resource[END_IDX] = EndIDx
590 /*
591 Resource pool stored in backend store as binary string.
592 Tracking the resource allocation will be done by setting the bits \
593 in the byte array. The index set will be the resource number allocated.
594 */
595 var TSData *bitmap.Threadsafe
596 if TSData = bitmap.NewTS(int(EndIDx)); TSData == nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700597 logger.Error("Failed to create a bitmap")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400598 return nil, errors.New("Failed to create bitmap")
599 }
divyadesaid26f6b12020-03-19 06:30:28 +0000600 for _, excludedID := range Excluded {
601 if excludedID < StartIDx || excludedID > EndIDx {
Scott Baker24f83e22020-03-30 16:14:28 -0700602 logger.Warnf("Cannot reserve %d. It must be in the range of [%d, %d]", excludedID,
divyadesaid26f6b12020-03-19 06:30:28 +0000603 StartIDx, EndIDx)
604 continue
605 }
606 PONRMgr.reserveID(TSData, StartIDx, excludedID)
607 }
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400608 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 -0400609
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400610 Value, err := json.Marshal(Resource)
611 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700612 logger.Errorf("Failed to marshall resource")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400613 return nil, err
614 }
615 return Value, err
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400616}
npujarec5762e2020-01-01 14:08:48 +0530617func (PONRMgr *PONResourceManager) GetResource(ctx context.Context, Path string) (map[string]interface{}, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400618 /*
619 Get resource from kv store.
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400620
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400621 :param path: path to get resource
622 :return: resource if resource present in kv store else None
623 */
624 //get resource from kv store
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400625
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400626 var Value []byte
627 Result := make(map[string]interface{})
628 var Str string
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400629
npujarec5762e2020-01-01 14:08:48 +0530630 Resource, err := PONRMgr.KVStore.Get(ctx, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400631 if (err != nil) || (Resource == nil) {
Scott Baker24f83e22020-03-30 16:14:28 -0700632 logger.Debugf("Resource unavailable at %s", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400633 return nil, err
634 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400635
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400636 Value, err = ToByte(Resource.Value)
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000637 if err != nil {
638 return nil, err
639 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400640
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400641 // decode resource fetched from backend store to dictionary
642 err = json.Unmarshal(Value, &Result)
643 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700644 logger.Error("Failed to decode resource")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400645 return Result, err
646 }
647 /*
648 resource pool in backend store stored as binary string whereas to
649 access the pool to generate/release IDs it need to be converted
650 as BitArray
651 */
652 Str, err = ToString(Result[POOL])
653 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700654 logger.Error("Failed to conver to kv pair to string")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400655 return Result, err
656 }
657 Decode64, _ := base64.StdEncoding.DecodeString(Str)
658 Result[POOL], err = ToByte(Decode64)
659 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700660 logger.Error("Failed to convert resource pool to byte")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400661 return Result, err
662 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400663
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400664 return Result, err
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400665}
666
667func (PONRMgr *PONResourceManager) GetPath(IntfID uint32, ResourceType string) string {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400668 /*
669 Get path for given resource type.
670 :param pon_intf_id: OLT PON interface id
671 :param resource_type: String to identify type of resource
672 :return: path for given resource type
673 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400674
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400675 /*
676 Get the shared pool for the given resource type.
677 all the resource ranges and the shared resource maps are initialized during the init.
678 */
679 SharedPoolID := PONRMgr.PonResourceRanges[PONRMgr.SharedIdxByType[ResourceType]].(uint32)
680 if SharedPoolID != 0 {
681 IntfID = SharedPoolID
682 }
683 var Path string
684 if ResourceType == ONU_ID {
685 Path = fmt.Sprintf(ONU_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
686 } else if ResourceType == ALLOC_ID {
687 Path = fmt.Sprintf(ALLOC_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
688 } else if ResourceType == GEMPORT_ID {
689 Path = fmt.Sprintf(GEMPORT_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
690 } else if ResourceType == FLOW_ID {
691 Path = fmt.Sprintf(FLOW_ID_POOL_PATH, PONRMgr.DeviceID, IntfID)
692 } else {
Scott Baker24f83e22020-03-30 16:14:28 -0700693 logger.Error("Invalid resource pool identifier")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400694 }
695 return Path
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400696}
697
npujarec5762e2020-01-01 14:08:48 +0530698func (PONRMgr *PONResourceManager) GetResourceID(ctx context.Context, IntfID uint32, ResourceType string, NumIDs uint32) ([]uint32, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400699 /*
700 Create alloc/gemport/onu/flow id for given OLT PON interface.
701 :param pon_intf_id: OLT PON interface id
702 :param resource_type: String to identify type of resource
703 :param num_of_id: required number of ids
704 :return list/uint32/None: list, uint32 or None if resource type is
705 alloc_id/gemport_id, onu_id or invalid type respectively
706 */
707 if NumIDs < 1 {
Scott Baker24f83e22020-03-30 16:14:28 -0700708 logger.Error("Invalid number of resources requested")
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000709 return nil, fmt.Errorf("Invalid number of resources requested %d", NumIDs)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400710 }
711 // delegate to the master instance if sharing enabled across instances
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400712
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400713 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
714 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
npujarec5762e2020-01-01 14:08:48 +0530715 return SharedResourceMgr.GetResourceID(ctx, IntfID, ResourceType, NumIDs)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400716 }
Scott Baker24f83e22020-03-30 16:14:28 -0700717 logger.Debugf("Fetching resource from %s rsrc mgr for resource %s", PONRMgr.Globalorlocal, ResourceType)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400718
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400719 Path := PONRMgr.GetPath(IntfID, ResourceType)
720 if Path == "" {
Scott Baker24f83e22020-03-30 16:14:28 -0700721 logger.Errorf("Failed to get path for resource type %s", ResourceType)
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000722 return nil, fmt.Errorf("Failed to get path for resource type %s", ResourceType)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400723 }
Scott Baker24f83e22020-03-30 16:14:28 -0700724 logger.Debugf("Get resource for type %s on path %s", ResourceType, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400725 var Result []uint32
726 var NextID uint32
npujarec5762e2020-01-01 14:08:48 +0530727 Resource, err := PONRMgr.GetResource(ctx, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400728 if (err == nil) && (ResourceType == ONU_ID) || (ResourceType == FLOW_ID) {
729 if NextID, err = PONRMgr.GenerateNextID(Resource); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700730 logger.Error("Failed to Generate ID")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400731 return Result, err
732 }
733 Result = append(Result, NextID)
734 } else if (err == nil) && ((ResourceType == GEMPORT_ID) || (ResourceType == ALLOC_ID)) {
735 if NumIDs == 1 {
736 if NextID, err = PONRMgr.GenerateNextID(Resource); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700737 logger.Error("Failed to Generate ID")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400738 return Result, err
739 }
740 Result = append(Result, NextID)
741 } else {
742 for NumIDs > 0 {
743 if NextID, err = PONRMgr.GenerateNextID(Resource); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700744 logger.Error("Failed to Generate ID")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400745 return Result, err
746 }
747 Result = append(Result, NextID)
748 NumIDs--
749 }
750 }
751 } else {
Scott Baker24f83e22020-03-30 16:14:28 -0700752 logger.Error("get resource failed")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400753 return Result, err
754 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400755
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400756 //Update resource in kv store
npujarec5762e2020-01-01 14:08:48 +0530757 if PONRMgr.UpdateResource(ctx, Path, Resource) != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700758 logger.Errorf("Failed to update resource %s", Path)
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000759 return nil, fmt.Errorf("Failed to update resource %s", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400760 }
761 return Result, nil
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400762}
763
764func checkValidResourceType(ResourceType string) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400765 KnownResourceTypes := []string{ONU_ID, ALLOC_ID, GEMPORT_ID, FLOW_ID}
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400766
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400767 for _, v := range KnownResourceTypes {
768 if v == ResourceType {
769 return true
770 }
771 }
772 return false
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400773}
774
npujarec5762e2020-01-01 14:08:48 +0530775func (PONRMgr *PONResourceManager) FreeResourceID(ctx context.Context, IntfID uint32, ResourceType string, ReleaseContent []uint32) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400776 /*
777 Release alloc/gemport/onu/flow id for given OLT PON interface.
778 :param pon_intf_id: OLT PON interface id
779 :param resource_type: String to identify type of resource
780 :param release_content: required number of ids
781 :return boolean: True if all IDs in given release_content release else False
782 */
Rohan Agrawal02f784d2020-02-14 09:34:02 +0000783 if !checkValidResourceType(ResourceType) {
Scott Baker24f83e22020-03-30 16:14:28 -0700784 logger.Error("Invalid resource type")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400785 return false
786 }
787 if ReleaseContent == nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700788 logger.Debug("Nothing to release")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400789 return true
790 }
791 // delegate to the master instance if sharing enabled across instances
792 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
793 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
npujarec5762e2020-01-01 14:08:48 +0530794 return SharedResourceMgr.FreeResourceID(ctx, IntfID, ResourceType, ReleaseContent)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400795 }
796 Path := PONRMgr.GetPath(IntfID, ResourceType)
797 if Path == "" {
Scott Baker24f83e22020-03-30 16:14:28 -0700798 logger.Error("Failed to get path")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400799 return false
800 }
npujarec5762e2020-01-01 14:08:48 +0530801 Resource, err := PONRMgr.GetResource(ctx, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400802 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700803 logger.Error("Failed to get resource")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400804 return false
805 }
806 for _, Val := range ReleaseContent {
807 PONRMgr.ReleaseID(Resource, Val)
808 }
npujarec5762e2020-01-01 14:08:48 +0530809 if PONRMgr.UpdateResource(ctx, Path, Resource) != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700810 logger.Errorf("Free resource for %s failed", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400811 return false
812 }
813 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400814}
815
npujarec5762e2020-01-01 14:08:48 +0530816func (PONRMgr *PONResourceManager) UpdateResource(ctx context.Context, Path string, Resource map[string]interface{}) error {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400817 /*
818 Update resource in resource kv store.
819 :param path: path to update resource
820 :param resource: resource need to be updated
821 :return boolean: True if resource updated in kv store else False
822 */
823 // TODO resource[POOL] = resource[POOL].bin
824 Value, err := json.Marshal(Resource)
825 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700826 logger.Error("failed to Marshal")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400827 return err
828 }
npujarec5762e2020-01-01 14:08:48 +0530829 err = PONRMgr.KVStore.Put(ctx, Path, Value)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400830 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700831 logger.Error("failed to put data to kv store %s", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400832 return err
833 }
834 return nil
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400835}
836
npujarec5762e2020-01-01 14:08:48 +0530837func (PONRMgr *PONResourceManager) ClearResourceIDPool(ctx context.Context, contIntfID uint32, ResourceType string) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400838 /*
839 Clear Resource Pool for a given Resource Type on a given PON Port.
840 :return boolean: True if removed else False
841 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400842
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400843 // delegate to the master instance if sharing enabled across instances
844 SharedResourceMgr := PONRMgr.SharedResourceMgrs[PONRMgr.SharedIdxByType[ResourceType]]
845 if SharedResourceMgr != nil && PONRMgr != SharedResourceMgr {
npujarec5762e2020-01-01 14:08:48 +0530846 return SharedResourceMgr.ClearResourceIDPool(ctx, contIntfID, ResourceType)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400847 }
npujarec5762e2020-01-01 14:08:48 +0530848 Path := PONRMgr.GetPath(contIntfID, ResourceType)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400849 if Path == "" {
Scott Baker24f83e22020-03-30 16:14:28 -0700850 logger.Error("Failed to get path")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400851 return false
852 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400853
npujarec5762e2020-01-01 14:08:48 +0530854 if err := PONRMgr.KVStore.Delete(ctx, Path); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700855 logger.Errorf("Failed to delete resource %s", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400856 return false
857 }
Scott Baker24f83e22020-03-30 16:14:28 -0700858 logger.Debugf("Cleared resource %s", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400859 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400860}
861
npujarec5762e2020-01-01 14:08:48 +0530862func (PONRMgr PONResourceManager) InitResourceMap(ctx context.Context, PONIntfONUID string) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400863 /*
864 Initialize resource map
865 :param pon_intf_onu_id: reference of PON interface id and onu id
866 */
867 // initialize pon_intf_onu_id tuple to alloc_ids map
868 AllocIDPath := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
869 var AllocIDs []byte
npujarec5762e2020-01-01 14:08:48 +0530870 Result := PONRMgr.KVStore.Put(ctx, AllocIDPath, AllocIDs)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400871 if Result != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700872 logger.Error("Failed to update the KV store")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400873 return
874 }
875 // initialize pon_intf_onu_id tuple to gemport_ids map
876 GEMPortIDPath := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
877 var GEMPortIDs []byte
npujarec5762e2020-01-01 14:08:48 +0530878 Result = PONRMgr.KVStore.Put(ctx, GEMPortIDPath, GEMPortIDs)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400879 if Result != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700880 logger.Error("Failed to update the KV store")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400881 return
882 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400883}
884
npujarec5762e2020-01-01 14:08:48 +0530885func (PONRMgr PONResourceManager) RemoveResourceMap(ctx context.Context, PONIntfONUID string) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400886 /*
887 Remove resource map
888 :param pon_intf_onu_id: reference of PON interface id and onu id
889 */
890 // remove pon_intf_onu_id tuple to alloc_ids map
891 var err error
892 AllocIDPath := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
npujarec5762e2020-01-01 14:08:48 +0530893 if err = PONRMgr.KVStore.Delete(ctx, AllocIDPath); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700894 logger.Errorf("Failed to remove resource %s", AllocIDPath)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400895 return false
896 }
897 // remove pon_intf_onu_id tuple to gemport_ids map
898 GEMPortIDPath := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
npujarec5762e2020-01-01 14:08:48 +0530899 err = PONRMgr.KVStore.Delete(ctx, GEMPortIDPath)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400900 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700901 logger.Errorf("Failed to remove resource %s", GEMPortIDPath)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400902 return false
903 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400904
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400905 FlowIDPath := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, PONIntfONUID)
npujarec5762e2020-01-01 14:08:48 +0530906 if FlowIDs, err := PONRMgr.KVStore.List(ctx, FlowIDPath); err != nil {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400907 for _, Flow := range FlowIDs {
908 FlowIDInfoPath := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, PONIntfONUID, Flow.Value)
npujarec5762e2020-01-01 14:08:48 +0530909 if err = PONRMgr.KVStore.Delete(ctx, FlowIDInfoPath); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700910 logger.Errorf("Failed to remove resource %s", FlowIDInfoPath)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400911 return false
912 }
913 }
914 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400915
npujarec5762e2020-01-01 14:08:48 +0530916 if err = PONRMgr.KVStore.Delete(ctx, FlowIDPath); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700917 logger.Errorf("Failed to remove resource %s", FlowIDPath)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400918 return false
919 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400920
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400921 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400922}
923
npujarec5762e2020-01-01 14:08:48 +0530924func (PONRMgr *PONResourceManager) GetCurrentAllocIDForOnu(ctx context.Context, IntfONUID string) []uint32 {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400925 /*
926 Get currently configured alloc ids for given pon_intf_onu_id
927 :param pon_intf_onu_id: reference of PON interface id and onu id
928 :return list: List of alloc_ids if available, else None
929 */
930 Path := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400931
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400932 var Data []uint32
npujarec5762e2020-01-01 14:08:48 +0530933 Value, err := PONRMgr.KVStore.Get(ctx, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400934 if err == nil {
935 if Value != nil {
936 Val, err := ToByte(Value.Value)
937 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700938 logger.Errorw("Failed to convert into byte array", log.Fields{"error": err})
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400939 return Data
940 }
941 if err = json.Unmarshal(Val, &Data); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700942 logger.Error("Failed to unmarshal", log.Fields{"error": err})
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400943 return Data
944 }
945 }
946 }
947 return Data
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400948}
949
npujarec5762e2020-01-01 14:08:48 +0530950func (PONRMgr *PONResourceManager) GetCurrentGEMPortIDsForOnu(ctx context.Context, IntfONUID string) []uint32 {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400951 /*
952 Get currently configured gemport ids for given pon_intf_onu_id
953 :param pon_intf_onu_id: reference of PON interface id and onu id
954 :return list: List of gemport IDs if available, else None
955 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400956
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400957 Path := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
Scott Baker24f83e22020-03-30 16:14:28 -0700958 logger.Debugf("Getting current gemports for %s", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400959 var Data []uint32
npujarec5762e2020-01-01 14:08:48 +0530960 Value, err := PONRMgr.KVStore.Get(ctx, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400961 if err == nil {
962 if Value != nil {
963 Val, _ := ToByte(Value.Value)
964 if err = json.Unmarshal(Val, &Data); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700965 logger.Errorw("Failed to unmarshal", log.Fields{"error": err})
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400966 return Data
967 }
968 }
969 } else {
Scott Baker24f83e22020-03-30 16:14:28 -0700970 logger.Errorf("Failed to get data from kvstore for %s", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400971 }
972 return Data
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400973}
974
npujarec5762e2020-01-01 14:08:48 +0530975func (PONRMgr *PONResourceManager) GetCurrentFlowIDsForOnu(ctx context.Context, IntfONUID string) []uint32 {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400976 /*
977 Get currently configured flow ids for given pon_intf_onu_id
978 :param pon_intf_onu_id: reference of PON interface id and onu id
979 :return list: List of Flow IDs if available, else None
980 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400981
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400982 Path := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400983
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400984 var Data []uint32
npujarec5762e2020-01-01 14:08:48 +0530985 Value, err := PONRMgr.KVStore.Get(ctx, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400986 if err == nil {
987 if Value != nil {
988 Val, _ := ToByte(Value.Value)
989 if err = json.Unmarshal(Val, &Data); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -0700990 logger.Error("Failed to unmarshal")
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400991 return Data
992 }
993 }
994 }
995 return Data
Matt Jeanneretcab955f2019-04-10 15:45:57 -0400996}
997
npujarec5762e2020-01-01 14:08:48 +0530998func (PONRMgr *PONResourceManager) GetFlowIDInfo(ctx context.Context, IntfONUID string, FlowID uint32, Data interface{}) error {
Matt Jeanneret384d8c92019-05-06 14:27:31 -0400999 /*
1000 Get flow details configured for the ONU.
1001 :param pon_intf_onu_id: reference of PON interface id and onu id
1002 :param flow_id: Flow Id reference
1003 :param Data: Result
1004 :return error: nil if no error in getting from KV store
1005 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001006
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001007 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001008
npujarec5762e2020-01-01 14:08:48 +05301009 Value, err := PONRMgr.KVStore.Get(ctx, Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001010 if err == nil {
1011 if Value != nil {
1012 Val, err := ToByte(Value.Value)
1013 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001014 logger.Errorw("Failed to convert flowinfo into byte array", log.Fields{"error": err})
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001015 return err
1016 }
1017 if err = json.Unmarshal(Val, Data); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001018 logger.Errorw("Failed to unmarshal", log.Fields{"error": err})
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001019 return err
1020 }
1021 }
1022 }
1023 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001024}
1025
npujarec5762e2020-01-01 14:08:48 +05301026func (PONRMgr *PONResourceManager) RemoveFlowIDInfo(ctx context.Context, IntfONUID string, FlowID uint32) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001027 /*
1028 Get flow_id details configured for the ONU.
1029 :param pon_intf_onu_id: reference of PON interface id and onu id
1030 :param flow_id: Flow Id reference
1031 */
1032 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001033
npujarec5762e2020-01-01 14:08:48 +05301034 if err := PONRMgr.KVStore.Delete(ctx, Path); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001035 logger.Errorf("Falied to remove resource %s", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001036 return false
1037 }
1038 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001039}
1040
npujarec5762e2020-01-01 14:08:48 +05301041func (PONRMgr *PONResourceManager) UpdateAllocIdsForOnu(ctx context.Context, IntfONUID string, AllocIDs []uint32) error {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001042 /*
1043 Update currently configured alloc ids for given pon_intf_onu_id
1044 :param pon_intf_onu_id: reference of PON interface id and onu id
1045 :param alloc_ids: list of alloc ids
1046 */
1047 var Value []byte
1048 var err error
1049 Path := fmt.Sprintf(ALLOC_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
1050 Value, err = json.Marshal(AllocIDs)
1051 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001052 logger.Error("failed to Marshal")
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001053 return err
1054 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001055
npujarec5762e2020-01-01 14:08:48 +05301056 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001057 logger.Errorf("Failed to update resource %s", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001058 return err
1059 }
1060 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001061}
1062
npujarec5762e2020-01-01 14:08:48 +05301063func (PONRMgr *PONResourceManager) UpdateGEMPortIDsForOnu(ctx context.Context, IntfONUID string, GEMPortIDs []uint32) error {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001064 /*
1065 Update currently configured gemport ids for given pon_intf_onu_id
1066 :param pon_intf_onu_id: reference of PON interface id and onu id
1067 :param gemport_ids: list of gem port ids
1068 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001069
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001070 var Value []byte
1071 var err error
1072 Path := fmt.Sprintf(GEMPORT_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
Scott Baker24f83e22020-03-30 16:14:28 -07001073 logger.Debugf("Updating gemport ids for %s", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001074 Value, err = json.Marshal(GEMPortIDs)
1075 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001076 logger.Error("failed to Marshal")
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001077 return err
1078 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001079
npujarec5762e2020-01-01 14:08:48 +05301080 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001081 logger.Errorf("Failed to update resource %s", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001082 return err
1083 }
1084 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001085}
1086
1087func checkForFlowIDInList(FlowIDList []uint32, FlowID uint32) (bool, uint32) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001088 /*
1089 Check for a flow id in a given list of flow IDs.
1090 :param FLowIDList: List of Flow IDs
1091 :param FlowID: Flowd to check in the list
1092 : return true and the index if present false otherwise.
1093 */
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001094
Rohan Agrawal02f784d2020-02-14 09:34:02 +00001095 for idx := range FlowIDList {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001096 if FlowID == FlowIDList[idx] {
1097 return true, uint32(idx)
1098 }
1099 }
1100 return false, 0
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001101}
1102
npujarec5762e2020-01-01 14:08:48 +05301103func (PONRMgr *PONResourceManager) UpdateFlowIDForOnu(ctx context.Context, IntfONUID string, FlowID uint32, Add bool) error {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001104 /*
1105 Update the flow_id list of the ONU (add or remove flow_id from the list)
1106 :param pon_intf_onu_id: reference of PON interface id and onu id
1107 :param flow_id: flow ID
1108 :param add: Boolean flag to indicate whether the flow_id should be
1109 added or removed from the list. Defaults to adding the flow.
1110 */
1111 var Value []byte
1112 var err error
1113 var RetVal bool
1114 var IDx uint32
1115 Path := fmt.Sprintf(FLOW_ID_RESOURCE_MAP_PATH, PONRMgr.DeviceID, IntfONUID)
npujarec5762e2020-01-01 14:08:48 +05301116 FlowIDs := PONRMgr.GetCurrentFlowIDsForOnu(ctx, IntfONUID)
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001117
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001118 if Add {
Rohan Agrawal02f784d2020-02-14 09:34:02 +00001119 if RetVal, _ = checkForFlowIDInList(FlowIDs, FlowID); RetVal {
1120 return nil
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001121 }
1122 FlowIDs = append(FlowIDs, FlowID)
1123 } else {
Rohan Agrawal02f784d2020-02-14 09:34:02 +00001124 if RetVal, IDx = checkForFlowIDInList(FlowIDs, FlowID); !RetVal {
1125 return nil
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001126 }
1127 // delete the index and shift
1128 FlowIDs = append(FlowIDs[:IDx], FlowIDs[IDx+1:]...)
1129 }
1130 Value, err = json.Marshal(FlowIDs)
1131 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001132 logger.Error("Failed to Marshal")
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001133 return err
1134 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001135
npujarec5762e2020-01-01 14:08:48 +05301136 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001137 logger.Errorf("Failed to update resource %s", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001138 return err
1139 }
1140 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001141}
1142
npujarec5762e2020-01-01 14:08:48 +05301143func (PONRMgr *PONResourceManager) UpdateFlowIDInfoForOnu(ctx context.Context, IntfONUID string, FlowID uint32, FlowData interface{}) error {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001144 /*
1145 Update any metadata associated with the flow_id. The flow_data could be json
1146 or any of other data structure. The resource manager doesnt care
1147 :param pon_intf_onu_id: reference of PON interface id and onu id
1148 :param flow_id: Flow ID
1149 :param flow_data: Flow data blob
1150 */
1151 var Value []byte
1152 var err error
1153 Path := fmt.Sprintf(FLOW_ID_INFO_PATH, PONRMgr.DeviceID, IntfONUID, FlowID)
1154 Value, err = json.Marshal(FlowData)
1155 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001156 logger.Error("failed to Marshal")
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001157 return err
1158 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001159
npujarec5762e2020-01-01 14:08:48 +05301160 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001161 logger.Errorf("Failed to update resource %s", Path)
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001162 return err
1163 }
1164 return err
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001165}
1166
1167func (PONRMgr *PONResourceManager) GenerateNextID(Resource map[string]interface{}) (uint32, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001168 /*
1169 Generate unique id having OFFSET as start
1170 :param resource: resource used to generate ID
1171 :return uint32: generated id
1172 */
1173 ByteArray, err := ToByte(Resource[POOL])
1174 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001175 logger.Error("Failed to convert resource to byte array")
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001176 return 0, err
1177 }
1178 Data := bitmap.TSFromData(ByteArray, false)
1179 if Data == nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001180 logger.Error("Failed to get data from byte array")
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001181 return 0, errors.New("Failed to get data from byte array")
1182 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001183
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001184 Len := Data.Len()
1185 var Idx int
1186 for Idx = 0; Idx < Len; Idx++ {
Rohan Agrawal02f784d2020-02-14 09:34:02 +00001187 if !Data.Get(Idx) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001188 break
1189 }
1190 }
1191 Data.Set(Idx, true)
1192 res := uint32(Resource[START_IDX].(float64))
1193 Resource[POOL] = Data.Data(false)
Scott Baker24f83e22020-03-30 16:14:28 -07001194 logger.Debugf("Generated ID for %d", (uint32(Idx) + res))
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001195 return (uint32(Idx) + res), err
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001196}
1197
1198func (PONRMgr *PONResourceManager) ReleaseID(Resource map[string]interface{}, Id uint32) bool {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001199 /*
1200 Release unique id having OFFSET as start index.
1201 :param resource: resource used to release ID
1202 :param unique_id: id need to be released
1203 */
1204 ByteArray, err := ToByte(Resource[POOL])
1205 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001206 logger.Error("Failed to convert resource to byte array")
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001207 return false
1208 }
1209 Data := bitmap.TSFromData(ByteArray, false)
1210 if Data == nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001211 logger.Error("Failed to get resource pool")
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001212 return false
1213 }
Rohan Agrawal02f784d2020-02-14 09:34:02 +00001214 Idx := Id - uint32(Resource[START_IDX].(float64))
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001215 Data.Set(int(Idx), false)
1216 Resource[POOL] = Data.Data(false)
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001217
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001218 return true
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001219}
1220
divyadesaid26f6b12020-03-19 06:30:28 +00001221/* Reserves a unique id in the specified resource pool.
1222:param Resource: resource used to reserve ID
1223:param Id: ID to be reserved
1224*/
1225func (PONRMgr *PONResourceManager) reserveID(TSData *bitmap.Threadsafe, StartIndex uint32, Id uint32) bool {
1226 Data := bitmap.TSFromData(TSData.Data(false), false)
1227 if Data == nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001228 logger.Error("Failed to get resource pool")
divyadesaid26f6b12020-03-19 06:30:28 +00001229 return false
1230 }
1231 Idx := Id - StartIndex
1232 Data.Set(int(Idx), true)
1233 return true
1234}
1235
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001236func (PONRMgr *PONResourceManager) GetTechnology() string {
1237 return PONRMgr.Technology
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001238}
1239
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001240func (PONRMgr *PONResourceManager) GetResourceTypeAllocID() string {
1241 return ALLOC_ID
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001242}
1243
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001244func (PONRMgr *PONResourceManager) GetResourceTypeGemPortID() string {
1245 return GEMPORT_ID
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001246}
1247
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001248// ToByte converts an interface value to a []byte. The interface should either be of
1249// a string type or []byte. Otherwise, an error is returned.
1250func ToByte(value interface{}) ([]byte, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001251 switch t := value.(type) {
1252 case []byte:
1253 return value.([]byte), nil
1254 case string:
1255 return []byte(value.(string)), nil
1256 default:
1257 return nil, fmt.Errorf("unexpected-type-%T", t)
1258 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001259}
1260
1261// ToString converts an interface value to a string. The interface should either be of
1262// a string type or []byte. Otherwise, an error is returned.
1263func ToString(value interface{}) (string, error) {
Matt Jeanneret384d8c92019-05-06 14:27:31 -04001264 switch t := value.(type) {
1265 case []byte:
1266 return string(value.([]byte)), nil
1267 case string:
1268 return value.(string), nil
1269 default:
1270 return "", fmt.Errorf("unexpected-type-%T", t)
1271 }
Matt Jeanneretcab955f2019-04-10 15:45:57 -04001272}
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001273
npujarec5762e2020-01-01 14:08:48 +05301274func (PONRMgr *PONResourceManager) AddOnuGemInfo(ctx context.Context, intfID uint32, onuGemData interface{}) error {
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001275 /*
1276 Update onugem info map,
1277 :param pon_intf_id: reference of PON interface id
1278 :param onuegmdata: onugem info map
1279 */
1280 var Value []byte
1281 var err error
1282 Path := fmt.Sprintf(ONU_GEM_INFO_PATH, PONRMgr.DeviceID, intfID)
1283 Value, err = json.Marshal(onuGemData)
1284 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001285 logger.Error("failed to Marshal")
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001286 return err
1287 }
1288
npujarec5762e2020-01-01 14:08:48 +05301289 if err = PONRMgr.KVStore.Put(ctx, Path, Value); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001290 logger.Errorf("Failed to update resource %s", Path)
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001291 return err
1292 }
1293 return err
1294}
1295
npujarec5762e2020-01-01 14:08:48 +05301296func (PONRMgr *PONResourceManager) GetOnuGemInfo(ctx context.Context, IntfId uint32, onuGemInfo interface{}) error {
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001297 /*
1298 Get onugeminfo map from kvstore
1299 :param intfid: refremce pon intfid
1300 :param onuGemInfo: onugem info to return from kv strore.
1301 */
1302 var Val []byte
1303
1304 path := fmt.Sprintf(ONU_GEM_INFO_PATH, PONRMgr.DeviceID, IntfId)
npujarec5762e2020-01-01 14:08:48 +05301305 value, err := PONRMgr.KVStore.Get(ctx, path)
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001306 if err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001307 logger.Errorw("Failed to get from kv store", log.Fields{"path": path})
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001308 return err
1309 } else if value == nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001310 logger.Debug("No onuinfo for path", log.Fields{"path": path})
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001311 return nil // returning nil as this could happen if there are no onus for the interface yet
1312 }
1313 if Val, err = kvstore.ToByte(value.Value); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001314 logger.Error("Failed to convert to byte array")
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001315 return err
1316 }
1317
1318 if err = json.Unmarshal(Val, &onuGemInfo); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001319 logger.Error("Failed to unmarshall")
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001320 return err
1321 }
Scott Baker24f83e22020-03-30 16:14:28 -07001322 logger.Debugw("found onuinfo from path", log.Fields{"path": path, "onuinfo": onuGemInfo})
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001323 return err
1324}
1325
npujarec5762e2020-01-01 14:08:48 +05301326func (PONRMgr *PONResourceManager) DelOnuGemInfoForIntf(ctx context.Context, intfId uint32) error {
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001327 /*
1328 delete onugem info for an interface from kvstore
1329 :param intfid: refremce pon intfid
1330 */
1331
1332 path := fmt.Sprintf(ONU_GEM_INFO_PATH, PONRMgr.DeviceID, intfId)
npujarec5762e2020-01-01 14:08:48 +05301333 if err := PONRMgr.KVStore.Delete(ctx, path); err != nil {
Scott Baker24f83e22020-03-30 16:14:28 -07001334 logger.Errorf("Falied to remove resource %s", path)
Scott Bakerc6e54cb2019-11-04 09:31:25 -08001335 return err
1336 }
1337 return nil
1338}