blob: 255e1be0fd6ed90941d9f294d135199d41251e68 [file] [log] [blame]
Girish Gowdra64503432020-01-07 10:59:10 +05301/*
2 * Copyright 2019-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//Package resourcemanager provides the utility for managing resources
18package core
19
20import (
Girish Gowdraaeceb842020-08-21 12:10:39 -070021 "sync"
Girish Gowdra64503432020-01-07 10:59:10 +053022
Girish Gowdra5d7d6442020-09-08 17:03:11 -070023 "github.com/opencord/voltha-lib-go/v4/pkg/log"
24 ponrmgr "github.com/opencord/voltha-lib-go/v4/pkg/ponresourcemanager"
25 "github.com/opencord/voltha-protos/v4/go/openolt"
Orhan Kupusoglu66b00d82020-03-13 12:06:33 +030026 "golang.org/x/net/context"
Girish Gowdra64503432020-01-07 10:59:10 +053027)
28
Girish Gowdra64503432020-01-07 10:59:10 +053029// OpenOltResourceMgr holds resource related information as provided below for each field
30type OpenOltResourceMgr struct {
31 deviceInfo *openolt.DeviceInfo
Girish Gowdraaeceb842020-08-21 12:10:39 -070032
33 // This protects concurrent onu_id allocate/delete calls on a per PON port basis
34 OnuIDMgmtLock []sync.RWMutex
35 // This protects concurrent flow_id allocate/delete calls. We do not need this on a
36 // per PON port basis as flow IDs are unique across the OLT.
37 FlowIDMgmtLock sync.RWMutex
38
39 // This protects concurrent GemID and AllocID allocate/delete calls on a per PON port basis
40 GemIDAllocIDLock []sync.RWMutex
41
Girish Gowdra64503432020-01-07 10:59:10 +053042 // array of pon resource managers per interface technology
43 ResourceMgrs map[uint32]*ponrmgr.PONResourceManager
Girish Gowdra5d7d6442020-09-08 17:03:11 -070044
45 flow_id uint64
Girish Gowdra64503432020-01-07 10:59:10 +053046}
47
48// NewResourceMgr init a New resource manager instance which in turn instantiates pon resource manager
49// instances according to technology. Initializes the default resource ranges for all
50// the resources.
51func NewResourceMgr(deviceID string, KVStoreHostPort string, kvStoreType string, deviceType string, devInfo *openolt.DeviceInfo) *OpenOltResourceMgr {
52 var ResourceMgr OpenOltResourceMgr
Girish Gowdra5d7d6442020-09-08 17:03:11 -070053 logger.Debugf(nil, "Init new resource manager")
Girish Gowdra64503432020-01-07 10:59:10 +053054
55 ResourceMgr.deviceInfo = devInfo
Girish Gowdraaeceb842020-08-21 12:10:39 -070056 NumPONPorts := devInfo.GetPonPorts()
57
58 ResourceMgr.OnuIDMgmtLock = make([]sync.RWMutex, NumPONPorts)
59 ResourceMgr.GemIDAllocIDLock = make([]sync.RWMutex, NumPONPorts)
60 ResourceMgr.FlowIDMgmtLock = sync.RWMutex{}
Girish Gowdra64503432020-01-07 10:59:10 +053061
62 Ranges := make(map[string]*openolt.DeviceInfo_DeviceResourceRanges)
63 RsrcMgrsByTech := make(map[string]*ponrmgr.PONResourceManager)
64 ResourceMgr.ResourceMgrs = make(map[uint32]*ponrmgr.PONResourceManager)
65
66 // TODO self.args = registry('main').get_args()
67
68 /*
69 If a legacy driver returns protobuf without any ranges,s synthesize one from
70 the legacy global per-device information. This, in theory, is temporary until
71 the legacy drivers are upgrade to support pool ranges.
72 */
73 if devInfo.Ranges == nil {
74 var ranges openolt.DeviceInfo_DeviceResourceRanges
75 ranges.Technology = devInfo.GetTechnology()
76
Girish Gowdra64503432020-01-07 10:59:10 +053077 var index uint32
78 for index = 0; index < NumPONPorts; index++ {
79 ranges.IntfIds = append(ranges.IntfIds, index)
80 }
81
82 var Pool openolt.DeviceInfo_DeviceResourceRanges_Pool
83 Pool.Type = openolt.DeviceInfo_DeviceResourceRanges_Pool_ONU_ID
84 Pool.Start = devInfo.OnuIdStart
85 Pool.End = devInfo.OnuIdEnd
86 Pool.Sharing = openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF
87 onuPool := Pool
88 ranges.Pools = append(ranges.Pools, &onuPool)
89
90 Pool.Type = openolt.DeviceInfo_DeviceResourceRanges_Pool_ALLOC_ID
91 Pool.Start = devInfo.AllocIdStart
92 Pool.End = devInfo.AllocIdEnd
93 Pool.Sharing = openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH
94 allocPool := Pool
95 ranges.Pools = append(ranges.Pools, &allocPool)
96
97 Pool.Type = openolt.DeviceInfo_DeviceResourceRanges_Pool_GEMPORT_ID
98 Pool.Start = devInfo.GemportIdStart
99 Pool.End = devInfo.GemportIdEnd
100 Pool.Sharing = openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH
101 gemPool := Pool
102 ranges.Pools = append(ranges.Pools, &gemPool)
103
104 Pool.Type = openolt.DeviceInfo_DeviceResourceRanges_Pool_FLOW_ID
105 Pool.Start = devInfo.FlowIdStart
106 Pool.End = devInfo.FlowIdEnd
107 Pool.Sharing = openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH
108 ranges.Pools = append(ranges.Pools, &Pool)
109 // Add to device info
110 devInfo.Ranges = append(devInfo.Ranges, &ranges)
111 }
112
113 // Create a separate Resource Manager instance for each range. This assumes that
114 // each technology is represented by only a single range
115 var GlobalPONRsrcMgr *ponrmgr.PONResourceManager
116 var err error
Girish Gowdra64503432020-01-07 10:59:10 +0530117 for _, TechRange := range devInfo.Ranges {
118 technology := TechRange.Technology
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700119 logger.Debugf(nil, "Device info technology %s", technology)
Girish Gowdra64503432020-01-07 10:59:10 +0530120 Ranges[technology] = TechRange
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700121 RsrcMgrsByTech[technology], err = ponrmgr.NewPONResourceManager(nil, technology, deviceType, deviceID,
122 kvStoreType, KVStoreHostPort)
Girish Gowdra64503432020-01-07 10:59:10 +0530123 if err != nil {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700124 logger.Errorf(nil, "Failed to create pon resource manager instance for technology %s", technology)
Girish Gowdra64503432020-01-07 10:59:10 +0530125 return nil
126 }
127 // resource_mgrs_by_tech[technology] = resource_mgr
128 if GlobalPONRsrcMgr == nil {
129 GlobalPONRsrcMgr = RsrcMgrsByTech[technology]
130 }
131 for _, IntfID := range TechRange.IntfIds {
132 ResourceMgr.ResourceMgrs[(IntfID)] = RsrcMgrsByTech[technology]
133 }
134 // self.initialize_device_resource_range_and_pool(resource_mgr, global_resource_mgr, arange)
135 InitializeDeviceResourceRangeAndPool(RsrcMgrsByTech[technology], GlobalPONRsrcMgr,
136 TechRange, devInfo)
137 }
138 // After we have initialized resource ranges, initialize the
139 // resource pools accordingly.
140 for _, PONRMgr := range RsrcMgrsByTech {
Orhan Kupusoglu66b00d82020-03-13 12:06:33 +0300141 _ = PONRMgr.InitDeviceResourcePool(context.Background())
Girish Gowdra64503432020-01-07 10:59:10 +0530142 }
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700143 logger.Info(nil, "Initialization of resource manager success!")
Girish Gowdra64503432020-01-07 10:59:10 +0530144 return &ResourceMgr
145}
146
147// InitializeDeviceResourceRangeAndPool initializes the resource range pool according to the sharing type, then apply
148// device specific information. If KV doesn't exist
149// or is broader than the device, the device's information will
150// dictate the range limits
151func InitializeDeviceResourceRangeAndPool(ponRMgr *ponrmgr.PONResourceManager, globalPONRMgr *ponrmgr.PONResourceManager,
152 techRange *openolt.DeviceInfo_DeviceResourceRanges, devInfo *openolt.DeviceInfo) {
153
154 // init the resource range pool according to the sharing type
155
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700156 logger.Debugf(nil, "Resource range pool init for technology %s", ponRMgr.Technology)
Girish Gowdra64503432020-01-07 10:59:10 +0530157 // first load from KV profiles
Orhan Kupusoglu66b00d82020-03-13 12:06:33 +0300158 status := ponRMgr.InitResourceRangesFromKVStore(context.Background())
Girish Gowdra64503432020-01-07 10:59:10 +0530159 if !status {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700160 logger.Debugf(nil, "Failed to load resource ranges from KV store for tech %s", ponRMgr.Technology)
Girish Gowdra64503432020-01-07 10:59:10 +0530161 }
162
163 /*
164 Then apply device specific information. If KV doesn't exist
165 or is broader than the device, the device's information will
166 dictate the range limits
167 */
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700168 logger.Debugf(nil, "Using device info to init pon resource ranges for tech", ponRMgr.Technology)
Girish Gowdra64503432020-01-07 10:59:10 +0530169
170 ONUIDStart := devInfo.OnuIdStart
171 ONUIDEnd := devInfo.OnuIdEnd
172 ONUIDShared := openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF
173 ONUIDSharedPoolID := uint32(0)
174 AllocIDStart := devInfo.AllocIdStart
175 AllocIDEnd := devInfo.AllocIdEnd
176 AllocIDShared := openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH // TODO EdgeCore/BAL limitation
177 AllocIDSharedPoolID := uint32(0)
178 GEMPortIDStart := devInfo.GemportIdStart
179 GEMPortIDEnd := devInfo.GemportIdEnd
180 GEMPortIDShared := openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH // TODO EdgeCore/BAL limitation
181 GEMPortIDSharedPoolID := uint32(0)
182 FlowIDStart := devInfo.FlowIdStart
183 FlowIDEnd := devInfo.FlowIdEnd
184 FlowIDShared := openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH // TODO EdgeCore/BAL limitation
185 FlowIDSharedPoolID := uint32(0)
186
187 var FirstIntfPoolID uint32
188 var SharedPoolID uint32
189
190 /*
191 * As a zero check is made against SharedPoolID to check whether the resources are shared across all intfs
192 * if resources are shared across interfaces then SharedPoolID is given a positive number.
193 */
194 for _, FirstIntfPoolID = range techRange.IntfIds {
195 // skip the intf id 0
196 if FirstIntfPoolID == 0 {
197 continue
198 }
199 break
200 }
201
202 for _, RangePool := range techRange.Pools {
203 if RangePool.Sharing == openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH {
204 SharedPoolID = FirstIntfPoolID
205 } else if RangePool.Sharing == openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_SAME_TECH {
206 SharedPoolID = FirstIntfPoolID
207 } else {
208 SharedPoolID = 0
209 }
210 if RangePool.Type == openolt.DeviceInfo_DeviceResourceRanges_Pool_ONU_ID {
211 ONUIDStart = RangePool.Start
212 ONUIDEnd = RangePool.End
213 ONUIDShared = RangePool.Sharing
214 ONUIDSharedPoolID = SharedPoolID
215 } else if RangePool.Type == openolt.DeviceInfo_DeviceResourceRanges_Pool_ALLOC_ID {
216 AllocIDStart = RangePool.Start
217 AllocIDEnd = RangePool.End
218 AllocIDShared = RangePool.Sharing
219 AllocIDSharedPoolID = SharedPoolID
220 } else if RangePool.Type == openolt.DeviceInfo_DeviceResourceRanges_Pool_GEMPORT_ID {
221 GEMPortIDStart = RangePool.Start
222 GEMPortIDEnd = RangePool.End
223 GEMPortIDShared = RangePool.Sharing
224 GEMPortIDSharedPoolID = SharedPoolID
225 } else if RangePool.Type == openolt.DeviceInfo_DeviceResourceRanges_Pool_FLOW_ID {
226 FlowIDStart = RangePool.Start
227 FlowIDEnd = RangePool.End
228 FlowIDShared = RangePool.Sharing
229 FlowIDSharedPoolID = SharedPoolID
230 }
231 }
232
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700233 logger.Debugw(nil, "Device info init", log.Fields{"technology": techRange.Technology,
Girish Gowdra64503432020-01-07 10:59:10 +0530234 "onu_id_start": ONUIDStart, "onu_id_end": ONUIDEnd, "onu_id_shared_pool_id": ONUIDSharedPoolID,
235 "alloc_id_start": AllocIDStart, "alloc_id_end": AllocIDEnd,
236 "alloc_id_shared_pool_id": AllocIDSharedPoolID,
237 "gemport_id_start": GEMPortIDStart, "gemport_id_end": GEMPortIDEnd,
238 "gemport_id_shared_pool_id": GEMPortIDSharedPoolID,
239 "flow_id_start": FlowIDStart,
240 "flow_id_end_idx": FlowIDEnd,
241 "flow_id_shared_pool_id": FlowIDSharedPoolID,
242 "intf_ids": techRange.IntfIds,
243 "uni_id_start": 0,
244 "uni_id_end_idx": 1, /*MaxUNIIDperONU()*/
245 })
246
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700247 ponRMgr.InitDefaultPONResourceRanges(nil, ONUIDStart, ONUIDEnd, ONUIDSharedPoolID,
Girish Gowdra64503432020-01-07 10:59:10 +0530248 AllocIDStart, AllocIDEnd, AllocIDSharedPoolID,
249 GEMPortIDStart, GEMPortIDEnd, GEMPortIDSharedPoolID,
250 FlowIDStart, FlowIDEnd, FlowIDSharedPoolID, 0, 1,
251 devInfo.PonPorts, techRange.IntfIds)
252
253 // For global sharing, make sure to refresh both local and global resource manager instances' range
254
255 if ONUIDShared == openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700256 globalPONRMgr.UpdateRanges(nil, ponrmgr.ONU_ID_START_IDX, ONUIDStart, ponrmgr.ONU_ID_END_IDX, ONUIDEnd,
Girish Gowdra64503432020-01-07 10:59:10 +0530257 "", 0, nil)
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700258 ponRMgr.UpdateRanges(nil, ponrmgr.ONU_ID_START_IDX, ONUIDStart, ponrmgr.ONU_ID_END_IDX, ONUIDEnd,
Girish Gowdra64503432020-01-07 10:59:10 +0530259 "", 0, globalPONRMgr)
260 }
261 if AllocIDShared == openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700262 globalPONRMgr.UpdateRanges(nil, ponrmgr.ALLOC_ID_START_IDX, AllocIDStart, ponrmgr.ALLOC_ID_END_IDX, AllocIDEnd,
Girish Gowdra64503432020-01-07 10:59:10 +0530263 "", 0, nil)
264
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700265 ponRMgr.UpdateRanges(nil, ponrmgr.ALLOC_ID_START_IDX, AllocIDStart, ponrmgr.ALLOC_ID_END_IDX, AllocIDEnd,
Girish Gowdra64503432020-01-07 10:59:10 +0530266 "", 0, globalPONRMgr)
267 }
268 if GEMPortIDShared == openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700269 globalPONRMgr.UpdateRanges(nil, ponrmgr.GEMPORT_ID_START_IDX, GEMPortIDStart, ponrmgr.GEMPORT_ID_END_IDX, GEMPortIDEnd,
Girish Gowdra64503432020-01-07 10:59:10 +0530270 "", 0, nil)
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700271 ponRMgr.UpdateRanges(nil, ponrmgr.GEMPORT_ID_START_IDX, GEMPortIDStart, ponrmgr.GEMPORT_ID_END_IDX, GEMPortIDEnd,
Girish Gowdra64503432020-01-07 10:59:10 +0530272 "", 0, globalPONRMgr)
273 }
274 if FlowIDShared == openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700275 globalPONRMgr.UpdateRanges(nil, ponrmgr.FLOW_ID_START_IDX, FlowIDStart, ponrmgr.FLOW_ID_END_IDX, FlowIDEnd,
Girish Gowdra64503432020-01-07 10:59:10 +0530276 "", 0, nil)
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700277 ponRMgr.UpdateRanges(nil, ponrmgr.FLOW_ID_START_IDX, FlowIDStart, ponrmgr.FLOW_ID_END_IDX, FlowIDEnd,
Girish Gowdra64503432020-01-07 10:59:10 +0530278 "", 0, globalPONRMgr)
279 }
280
281 // Make sure loaded range fits the platform bit encoding ranges
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700282 ponRMgr.UpdateRanges(nil, ponrmgr.UNI_ID_START_IDX, 0, ponrmgr.UNI_ID_END_IDX /* TODO =OpenOltPlatform.MAX_UNIS_PER_ONU-1*/, 1, "", 0, nil)
Girish Gowdra64503432020-01-07 10:59:10 +0530283}
284
285// Delete clears used resources for the particular olt device being deleted
286func (RsrcMgr *OpenOltResourceMgr) Delete() error {
Girish Gowdra64503432020-01-07 10:59:10 +0530287 for _, rsrcMgr := range RsrcMgr.ResourceMgrs {
Orhan Kupusoglu66b00d82020-03-13 12:06:33 +0300288 if err := rsrcMgr.ClearDeviceResourcePool(context.Background()); err != nil {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700289 logger.Debug(nil, "Failed to clear device resource pool")
Girish Gowdra64503432020-01-07 10:59:10 +0530290 return err
291 }
292 }
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700293 logger.Debug(nil, "Cleared device resource pool")
Girish Gowdra64503432020-01-07 10:59:10 +0530294 return nil
295}
296
297// GetONUID returns the available OnuID for the given pon-port
298func (RsrcMgr *OpenOltResourceMgr) GetONUID(ponIntfID uint32) (uint32, error) {
Girish Gowdraaeceb842020-08-21 12:10:39 -0700299 RsrcMgr.OnuIDMgmtLock[ponIntfID].Lock()
300 defer RsrcMgr.OnuIDMgmtLock[ponIntfID].Unlock()
Girish Gowdra64503432020-01-07 10:59:10 +0530301 // Check if Pon Interface ID is present in Resource-manager-map
Girish Gowdraaeceb842020-08-21 12:10:39 -0700302 ONUIDs, err := RsrcMgr.ResourceMgrs[ponIntfID].GetResourceID(context.Background(), ponIntfID,
Girish Gowdra64503432020-01-07 10:59:10 +0530303 ponrmgr.ONU_ID, 1)
304 if err != nil {
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700305 logger.Errorf(nil, "Failed to get resource for interface %d for type %s",
Girish Gowdra64503432020-01-07 10:59:10 +0530306 ponIntfID, ponrmgr.ONU_ID)
Girish Gowdraaeceb842020-08-21 12:10:39 -0700307 return uint32(0), err
Girish Gowdra64503432020-01-07 10:59:10 +0530308 }
Girish Gowdraaeceb842020-08-21 12:10:39 -0700309 return ONUIDs[0], err
Girish Gowdra64503432020-01-07 10:59:10 +0530310}
311
Girish Gowdraaeceb842020-08-21 12:10:39 -0700312// GetFlowID return flow ID for a given pon interface id, onu id and uni id
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700313func (RsrcMgr *OpenOltResourceMgr) GetFlowID(ctx context.Context, ponIntfID uint32) (uint64, error) {
Girish Gowdraaeceb842020-08-21 12:10:39 -0700314 RsrcMgr.FlowIDMgmtLock.Lock()
315 defer RsrcMgr.FlowIDMgmtLock.Unlock()
Girish Gowdra5d7d6442020-09-08 17:03:11 -0700316 RsrcMgr.flow_id++
317 return RsrcMgr.flow_id, nil
Girish Gowdra64503432020-01-07 10:59:10 +0530318}