blob: d8674c9f5f3621f95da098b5133356b969a2b908 [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 Gowdra64503432020-01-07 10:59:10 +053021 "strconv"
22 "strings"
Girish Gowdraaeceb842020-08-21 12:10:39 -070023 "sync"
Girish Gowdra64503432020-01-07 10:59:10 +053024
Orhan Kupusoglu66b00d82020-03-13 12:06:33 +030025 "github.com/opencord/voltha-lib-go/v3/pkg/log"
26 ponrmgr "github.com/opencord/voltha-lib-go/v3/pkg/ponresourcemanager"
27 "github.com/opencord/voltha-protos/v3/go/openolt"
28 "golang.org/x/net/context"
Girish Gowdra64503432020-01-07 10:59:10 +053029)
30
31func init() {
32 _, _ = log.AddPackage(log.JSON, log.DebugLevel, nil)
33}
34
35// OpenOltResourceMgr holds resource related information as provided below for each field
36type OpenOltResourceMgr struct {
37 deviceInfo *openolt.DeviceInfo
Girish Gowdraaeceb842020-08-21 12:10:39 -070038
39 // This protects concurrent onu_id allocate/delete calls on a per PON port basis
40 OnuIDMgmtLock []sync.RWMutex
41 // This protects concurrent flow_id allocate/delete calls. We do not need this on a
42 // per PON port basis as flow IDs are unique across the OLT.
43 FlowIDMgmtLock sync.RWMutex
44
45 // This protects concurrent GemID and AllocID allocate/delete calls on a per PON port basis
46 GemIDAllocIDLock []sync.RWMutex
47
Girish Gowdra64503432020-01-07 10:59:10 +053048 // array of pon resource managers per interface technology
49 ResourceMgrs map[uint32]*ponrmgr.PONResourceManager
50}
51
52// NewResourceMgr init a New resource manager instance which in turn instantiates pon resource manager
53// instances according to technology. Initializes the default resource ranges for all
54// the resources.
55func NewResourceMgr(deviceID string, KVStoreHostPort string, kvStoreType string, deviceType string, devInfo *openolt.DeviceInfo) *OpenOltResourceMgr {
56 var ResourceMgr OpenOltResourceMgr
57 log.Debugf("Init new resource manager")
58
59 ResourceMgr.deviceInfo = devInfo
Girish Gowdraaeceb842020-08-21 12:10:39 -070060 NumPONPorts := devInfo.GetPonPorts()
61
62 ResourceMgr.OnuIDMgmtLock = make([]sync.RWMutex, NumPONPorts)
63 ResourceMgr.GemIDAllocIDLock = make([]sync.RWMutex, NumPONPorts)
64 ResourceMgr.FlowIDMgmtLock = sync.RWMutex{}
Girish Gowdra64503432020-01-07 10:59:10 +053065
66 Ranges := make(map[string]*openolt.DeviceInfo_DeviceResourceRanges)
67 RsrcMgrsByTech := make(map[string]*ponrmgr.PONResourceManager)
68 ResourceMgr.ResourceMgrs = make(map[uint32]*ponrmgr.PONResourceManager)
69
70 // TODO self.args = registry('main').get_args()
71
72 /*
73 If a legacy driver returns protobuf without any ranges,s synthesize one from
74 the legacy global per-device information. This, in theory, is temporary until
75 the legacy drivers are upgrade to support pool ranges.
76 */
77 if devInfo.Ranges == nil {
78 var ranges openolt.DeviceInfo_DeviceResourceRanges
79 ranges.Technology = devInfo.GetTechnology()
80
Girish Gowdra64503432020-01-07 10:59:10 +053081 var index uint32
82 for index = 0; index < NumPONPorts; index++ {
83 ranges.IntfIds = append(ranges.IntfIds, index)
84 }
85
86 var Pool openolt.DeviceInfo_DeviceResourceRanges_Pool
87 Pool.Type = openolt.DeviceInfo_DeviceResourceRanges_Pool_ONU_ID
88 Pool.Start = devInfo.OnuIdStart
89 Pool.End = devInfo.OnuIdEnd
90 Pool.Sharing = openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF
91 onuPool := Pool
92 ranges.Pools = append(ranges.Pools, &onuPool)
93
94 Pool.Type = openolt.DeviceInfo_DeviceResourceRanges_Pool_ALLOC_ID
95 Pool.Start = devInfo.AllocIdStart
96 Pool.End = devInfo.AllocIdEnd
97 Pool.Sharing = openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH
98 allocPool := Pool
99 ranges.Pools = append(ranges.Pools, &allocPool)
100
101 Pool.Type = openolt.DeviceInfo_DeviceResourceRanges_Pool_GEMPORT_ID
102 Pool.Start = devInfo.GemportIdStart
103 Pool.End = devInfo.GemportIdEnd
104 Pool.Sharing = openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH
105 gemPool := Pool
106 ranges.Pools = append(ranges.Pools, &gemPool)
107
108 Pool.Type = openolt.DeviceInfo_DeviceResourceRanges_Pool_FLOW_ID
109 Pool.Start = devInfo.FlowIdStart
110 Pool.End = devInfo.FlowIdEnd
111 Pool.Sharing = openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH
112 ranges.Pools = append(ranges.Pools, &Pool)
113 // Add to device info
114 devInfo.Ranges = append(devInfo.Ranges, &ranges)
115 }
116
117 // Create a separate Resource Manager instance for each range. This assumes that
118 // each technology is represented by only a single range
119 var GlobalPONRsrcMgr *ponrmgr.PONResourceManager
120 var err error
121 IPPort := strings.Split(KVStoreHostPort, ":")
122 for _, TechRange := range devInfo.Ranges {
123 technology := TechRange.Technology
124 log.Debugf("Device info technology %s", technology)
125 Ranges[technology] = TechRange
126 port, _ := strconv.Atoi(IPPort[1])
127 RsrcMgrsByTech[technology], err = ponrmgr.NewPONResourceManager(technology, deviceType, deviceID,
128 kvStoreType, IPPort[0], port)
129 if err != nil {
130 log.Errorf("Failed to create pon resource manager instance for technology %s", technology)
131 return nil
132 }
133 // resource_mgrs_by_tech[technology] = resource_mgr
134 if GlobalPONRsrcMgr == nil {
135 GlobalPONRsrcMgr = RsrcMgrsByTech[technology]
136 }
137 for _, IntfID := range TechRange.IntfIds {
138 ResourceMgr.ResourceMgrs[(IntfID)] = RsrcMgrsByTech[technology]
139 }
140 // self.initialize_device_resource_range_and_pool(resource_mgr, global_resource_mgr, arange)
141 InitializeDeviceResourceRangeAndPool(RsrcMgrsByTech[technology], GlobalPONRsrcMgr,
142 TechRange, devInfo)
143 }
144 // After we have initialized resource ranges, initialize the
145 // resource pools accordingly.
146 for _, PONRMgr := range RsrcMgrsByTech {
Orhan Kupusoglu66b00d82020-03-13 12:06:33 +0300147 _ = PONRMgr.InitDeviceResourcePool(context.Background())
Girish Gowdra64503432020-01-07 10:59:10 +0530148 }
149 log.Info("Initialization of resource manager success!")
150 return &ResourceMgr
151}
152
153// InitializeDeviceResourceRangeAndPool initializes the resource range pool according to the sharing type, then apply
154// device specific information. If KV doesn't exist
155// or is broader than the device, the device's information will
156// dictate the range limits
157func InitializeDeviceResourceRangeAndPool(ponRMgr *ponrmgr.PONResourceManager, globalPONRMgr *ponrmgr.PONResourceManager,
158 techRange *openolt.DeviceInfo_DeviceResourceRanges, devInfo *openolt.DeviceInfo) {
159
160 // init the resource range pool according to the sharing type
161
162 log.Debugf("Resource range pool init for technology %s", ponRMgr.Technology)
163 // first load from KV profiles
Orhan Kupusoglu66b00d82020-03-13 12:06:33 +0300164 status := ponRMgr.InitResourceRangesFromKVStore(context.Background())
Girish Gowdra64503432020-01-07 10:59:10 +0530165 if !status {
166 log.Debugf("Failed to load resource ranges from KV store for tech %s", ponRMgr.Technology)
167 }
168
169 /*
170 Then apply device specific information. If KV doesn't exist
171 or is broader than the device, the device's information will
172 dictate the range limits
173 */
174 log.Debugf("Using device info to init pon resource ranges for tech", ponRMgr.Technology)
175
176 ONUIDStart := devInfo.OnuIdStart
177 ONUIDEnd := devInfo.OnuIdEnd
178 ONUIDShared := openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF
179 ONUIDSharedPoolID := uint32(0)
180 AllocIDStart := devInfo.AllocIdStart
181 AllocIDEnd := devInfo.AllocIdEnd
182 AllocIDShared := openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH // TODO EdgeCore/BAL limitation
183 AllocIDSharedPoolID := uint32(0)
184 GEMPortIDStart := devInfo.GemportIdStart
185 GEMPortIDEnd := devInfo.GemportIdEnd
186 GEMPortIDShared := openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH // TODO EdgeCore/BAL limitation
187 GEMPortIDSharedPoolID := uint32(0)
188 FlowIDStart := devInfo.FlowIdStart
189 FlowIDEnd := devInfo.FlowIdEnd
190 FlowIDShared := openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH // TODO EdgeCore/BAL limitation
191 FlowIDSharedPoolID := uint32(0)
192
193 var FirstIntfPoolID uint32
194 var SharedPoolID uint32
195
196 /*
197 * As a zero check is made against SharedPoolID to check whether the resources are shared across all intfs
198 * if resources are shared across interfaces then SharedPoolID is given a positive number.
199 */
200 for _, FirstIntfPoolID = range techRange.IntfIds {
201 // skip the intf id 0
202 if FirstIntfPoolID == 0 {
203 continue
204 }
205 break
206 }
207
208 for _, RangePool := range techRange.Pools {
209 if RangePool.Sharing == openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH {
210 SharedPoolID = FirstIntfPoolID
211 } else if RangePool.Sharing == openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_SAME_TECH {
212 SharedPoolID = FirstIntfPoolID
213 } else {
214 SharedPoolID = 0
215 }
216 if RangePool.Type == openolt.DeviceInfo_DeviceResourceRanges_Pool_ONU_ID {
217 ONUIDStart = RangePool.Start
218 ONUIDEnd = RangePool.End
219 ONUIDShared = RangePool.Sharing
220 ONUIDSharedPoolID = SharedPoolID
221 } else if RangePool.Type == openolt.DeviceInfo_DeviceResourceRanges_Pool_ALLOC_ID {
222 AllocIDStart = RangePool.Start
223 AllocIDEnd = RangePool.End
224 AllocIDShared = RangePool.Sharing
225 AllocIDSharedPoolID = SharedPoolID
226 } else if RangePool.Type == openolt.DeviceInfo_DeviceResourceRanges_Pool_GEMPORT_ID {
227 GEMPortIDStart = RangePool.Start
228 GEMPortIDEnd = RangePool.End
229 GEMPortIDShared = RangePool.Sharing
230 GEMPortIDSharedPoolID = SharedPoolID
231 } else if RangePool.Type == openolt.DeviceInfo_DeviceResourceRanges_Pool_FLOW_ID {
232 FlowIDStart = RangePool.Start
233 FlowIDEnd = RangePool.End
234 FlowIDShared = RangePool.Sharing
235 FlowIDSharedPoolID = SharedPoolID
236 }
237 }
238
239 log.Debugw("Device info init", log.Fields{"technology": techRange.Technology,
240 "onu_id_start": ONUIDStart, "onu_id_end": ONUIDEnd, "onu_id_shared_pool_id": ONUIDSharedPoolID,
241 "alloc_id_start": AllocIDStart, "alloc_id_end": AllocIDEnd,
242 "alloc_id_shared_pool_id": AllocIDSharedPoolID,
243 "gemport_id_start": GEMPortIDStart, "gemport_id_end": GEMPortIDEnd,
244 "gemport_id_shared_pool_id": GEMPortIDSharedPoolID,
245 "flow_id_start": FlowIDStart,
246 "flow_id_end_idx": FlowIDEnd,
247 "flow_id_shared_pool_id": FlowIDSharedPoolID,
248 "intf_ids": techRange.IntfIds,
249 "uni_id_start": 0,
250 "uni_id_end_idx": 1, /*MaxUNIIDperONU()*/
251 })
252
253 ponRMgr.InitDefaultPONResourceRanges(ONUIDStart, ONUIDEnd, ONUIDSharedPoolID,
254 AllocIDStart, AllocIDEnd, AllocIDSharedPoolID,
255 GEMPortIDStart, GEMPortIDEnd, GEMPortIDSharedPoolID,
256 FlowIDStart, FlowIDEnd, FlowIDSharedPoolID, 0, 1,
257 devInfo.PonPorts, techRange.IntfIds)
258
259 // For global sharing, make sure to refresh both local and global resource manager instances' range
260
261 if ONUIDShared == openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH {
262 globalPONRMgr.UpdateRanges(ponrmgr.ONU_ID_START_IDX, ONUIDStart, ponrmgr.ONU_ID_END_IDX, ONUIDEnd,
263 "", 0, nil)
264 ponRMgr.UpdateRanges(ponrmgr.ONU_ID_START_IDX, ONUIDStart, ponrmgr.ONU_ID_END_IDX, ONUIDEnd,
265 "", 0, globalPONRMgr)
266 }
267 if AllocIDShared == openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH {
268 globalPONRMgr.UpdateRanges(ponrmgr.ALLOC_ID_START_IDX, AllocIDStart, ponrmgr.ALLOC_ID_END_IDX, AllocIDEnd,
269 "", 0, nil)
270
271 ponRMgr.UpdateRanges(ponrmgr.ALLOC_ID_START_IDX, AllocIDStart, ponrmgr.ALLOC_ID_END_IDX, AllocIDEnd,
272 "", 0, globalPONRMgr)
273 }
274 if GEMPortIDShared == openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH {
275 globalPONRMgr.UpdateRanges(ponrmgr.GEMPORT_ID_START_IDX, GEMPortIDStart, ponrmgr.GEMPORT_ID_END_IDX, GEMPortIDEnd,
276 "", 0, nil)
277 ponRMgr.UpdateRanges(ponrmgr.GEMPORT_ID_START_IDX, GEMPortIDStart, ponrmgr.GEMPORT_ID_END_IDX, GEMPortIDEnd,
278 "", 0, globalPONRMgr)
279 }
280 if FlowIDShared == openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH {
281 globalPONRMgr.UpdateRanges(ponrmgr.FLOW_ID_START_IDX, FlowIDStart, ponrmgr.FLOW_ID_END_IDX, FlowIDEnd,
282 "", 0, nil)
283 ponRMgr.UpdateRanges(ponrmgr.FLOW_ID_START_IDX, FlowIDStart, ponrmgr.FLOW_ID_END_IDX, FlowIDEnd,
284 "", 0, globalPONRMgr)
285 }
286
287 // Make sure loaded range fits the platform bit encoding ranges
288 ponRMgr.UpdateRanges(ponrmgr.UNI_ID_START_IDX, 0, ponrmgr.UNI_ID_END_IDX /* TODO =OpenOltPlatform.MAX_UNIS_PER_ONU-1*/, 1, "", 0, nil)
289}
290
291// Delete clears used resources for the particular olt device being deleted
292func (RsrcMgr *OpenOltResourceMgr) Delete() error {
Girish Gowdra64503432020-01-07 10:59:10 +0530293 for _, rsrcMgr := range RsrcMgr.ResourceMgrs {
Orhan Kupusoglu66b00d82020-03-13 12:06:33 +0300294 if err := rsrcMgr.ClearDeviceResourcePool(context.Background()); err != nil {
Girish Gowdra64503432020-01-07 10:59:10 +0530295 log.Debug("Failed to clear device resource pool")
296 return err
297 }
298 }
299 log.Debug("Cleared device resource pool")
300 return nil
301}
302
303// GetONUID returns the available OnuID for the given pon-port
304func (RsrcMgr *OpenOltResourceMgr) GetONUID(ponIntfID uint32) (uint32, error) {
Girish Gowdraaeceb842020-08-21 12:10:39 -0700305 RsrcMgr.OnuIDMgmtLock[ponIntfID].Lock()
306 defer RsrcMgr.OnuIDMgmtLock[ponIntfID].Unlock()
Girish Gowdra64503432020-01-07 10:59:10 +0530307 // Check if Pon Interface ID is present in Resource-manager-map
Girish Gowdraaeceb842020-08-21 12:10:39 -0700308 ONUIDs, err := RsrcMgr.ResourceMgrs[ponIntfID].GetResourceID(context.Background(), ponIntfID,
Girish Gowdra64503432020-01-07 10:59:10 +0530309 ponrmgr.ONU_ID, 1)
310 if err != nil {
311 log.Errorf("Failed to get resource for interface %d for type %s",
312 ponIntfID, ponrmgr.ONU_ID)
Girish Gowdraaeceb842020-08-21 12:10:39 -0700313 return uint32(0), err
Girish Gowdra64503432020-01-07 10:59:10 +0530314 }
Girish Gowdraaeceb842020-08-21 12:10:39 -0700315 return ONUIDs[0], err
Girish Gowdra64503432020-01-07 10:59:10 +0530316}
317
Girish Gowdraaeceb842020-08-21 12:10:39 -0700318// GetFlowID return flow ID for a given pon interface id, onu id and uni id
319func (RsrcMgr *OpenOltResourceMgr) GetFlowID(ctx context.Context, ponIntfID uint32) (uint32, error) {
320 RsrcMgr.FlowIDMgmtLock.Lock()
321 defer RsrcMgr.FlowIDMgmtLock.Unlock()
322 FlowIDs, err := RsrcMgr.ResourceMgrs[ponIntfID].GetResourceID(context.Background(), ponIntfID,
323 ponrmgr.FLOW_ID, 1)
Girish Gowdra64503432020-01-07 10:59:10 +0530324 if err != nil {
Girish Gowdraaeceb842020-08-21 12:10:39 -0700325 log.Errorf("Failed to get resource for interface %d for type %s",
326 ponIntfID, ponrmgr.FLOW_ID)
327 return uint32(0), err
Girish Gowdra64503432020-01-07 10:59:10 +0530328 }
Girish Gowdraaeceb842020-08-21 12:10:39 -0700329 return FlowIDs[0], err
Girish Gowdra64503432020-01-07 10:59:10 +0530330}