blob: 706a6854aa296409f741c82a455d445721b97fd1 [file] [log] [blame]
Chip Boling67b674a2019-02-08 11:42:18 -06001#
2# Copyright 2018 the original author or authors.
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#
Zack Williams84a71e92019-11-15 09:00:19 -070016from __future__ import absolute_import
Matteo Scandolo013426b2020-11-24 11:15:59 -080017
18import os
19
Chip Boling67b674a2019-02-08 11:42:18 -060020import json
21import ast
22from collections import namedtuple
23import structlog
24from enum import Enum
25
Matt Jeanneret6eb68172019-03-31 10:53:44 -040026from pyvoltha.common.config.config_backend import ConsulStore
27from pyvoltha.common.config.config_backend import EtcdStore
Chip Boling67b674a2019-02-08 11:42:18 -060028from pyvoltha.common.utils.registry import registry
William Kurkianede82e92019-03-05 13:02:57 -050029from voltha_protos import openolt_pb2
Zack Williams84a71e92019-11-15 09:00:19 -070030from six.moves import range
Chip Boling67b674a2019-02-08 11:42:18 -060031
32# logger
33log = structlog.get_logger()
34
35DEFAULT_TECH_PROFILE_TABLE_ID = 64
36
37# Enums used while creating TechProfileInstance
38Direction = Enum('Direction', ['UPSTREAM', 'DOWNSTREAM', 'BIDIRECTIONAL'],
39 start=0)
40SchedulingPolicy = Enum('SchedulingPolicy',
41 ['WRR', 'StrictPriority', 'Hybrid'], start=0)
42AdditionalBW = Enum('AdditionalBW', ['None', 'NA', 'BestEffort', 'Auto'],
43 start=0)
44DiscardPolicy = Enum('DiscardPolicy',
45 ['TailDrop', 'WTailDrop', 'RED', 'WRED'], start=0)
46InferredAdditionBWIndication = Enum('InferredAdditionBWIndication',
47 ['None', 'NoneAssured', 'BestEffort'],
48 start=0)
49
50
51class InstanceControl(object):
52 # Default value constants
53 ONU_DEFAULT_INSTANCE = 'multi-instance'
54 UNI_DEFAULT_INSTANCE = 'single-instance'
55 DEFAULT_NUM_GEM_PORTS = 1
56 DEFAULT_GEM_PAYLOAD_SIZE = 'auto'
57
58 def __init__(self, onu=ONU_DEFAULT_INSTANCE,
59 uni=UNI_DEFAULT_INSTANCE,
60 num_gem_ports=DEFAULT_NUM_GEM_PORTS,
61 max_gem_payload_size=DEFAULT_GEM_PAYLOAD_SIZE):
62 self.onu = onu
63 self.uni = uni
64 self.num_gem_ports = num_gem_ports
65 self.max_gem_payload_size = max_gem_payload_size
66
67
68class Scheduler(object):
69 # Default value constants
70 DEFAULT_ADDITIONAL_BW = 'auto'
71 DEFAULT_PRIORITY = 0
72 DEFAULT_WEIGHT = 0
73 DEFAULT_Q_SCHED_POLICY = 'hybrid'
74
75 def __init__(self, direction, additional_bw=DEFAULT_ADDITIONAL_BW,
76 priority=DEFAULT_PRIORITY,
77 weight=DEFAULT_WEIGHT,
78 q_sched_policy=DEFAULT_Q_SCHED_POLICY):
79 self.direction = direction
80 self.additional_bw = additional_bw
81 self.priority = priority
82 self.weight = weight
83 self.q_sched_policy = q_sched_policy
84
85
86class GemPortAttribute(object):
87 # Default value constants
88 DEFAULT_AES_ENCRYPTION = 'True'
89 DEFAULT_PRIORITY_Q = 0
90 DEFAULT_WEIGHT = 0
91 DEFAULT_MAX_Q_SIZE = 'auto'
92 DEFAULT_DISCARD_POLICY = DiscardPolicy.TailDrop.name
93
94 def __init__(self, pbit_map, discard_config,
95 aes_encryption=DEFAULT_AES_ENCRYPTION,
96 scheduling_policy=SchedulingPolicy.WRR.name,
97 priority_q=DEFAULT_PRIORITY_Q,
98 weight=DEFAULT_WEIGHT,
99 max_q_size=DEFAULT_MAX_Q_SIZE,
100 discard_policy=DiscardPolicy.TailDrop.name):
101 self.max_q_size = max_q_size
102 self.pbit_map = pbit_map
103 self.aes_encryption = aes_encryption
104 self.scheduling_policy = scheduling_policy
105 self.priority_q = priority_q
106 self.weight = weight
107 self.discard_policy = discard_policy
108 self.discard_config = discard_config
109
110
111class DiscardConfig(object):
112 # Default value constants
113 DEFAULT_MIN_THRESHOLD = 0
114 DEFAULT_MAX_THRESHOLD = 0
115 DEFAULT_MAX_PROBABILITY = 0
116
117 def __init__(self, min_threshold=DEFAULT_MIN_THRESHOLD,
118 max_threshold=DEFAULT_MAX_THRESHOLD,
119 max_probability=DEFAULT_MAX_PROBABILITY):
120 self.min_threshold = min_threshold
121 self.max_threshold = max_threshold
122 self.max_probability = max_probability
123
124
125class TechProfile(object):
126 # Constants used in default tech profile
127 DEFAULT_TECH_PROFILE_NAME = 'Default_1tcont_1gem_Profile'
128 DEFAULT_VERSION = 1.0
129 DEFAULT_GEMPORTS_COUNT = 1
130 pbits = ['0b11111111']
131
132 # Tech profile path prefix in kv store
Matteo Scandolo013426b2020-11-24 11:15:59 -0800133 if "KV_STORE_DATAPATH_PREFIX" in os.environ:
134 kv_store_prefix = os.environ["KV_STORE_DATAPATH_PREFIX"]
135 else:
136 kv_store_prefix = "service/voltha"
137 KV_STORE_TECH_PROFILE_PATH_PREFIX = '%s/technology_profiles' % kv_store_prefix
138
139 log.debug("kv-store-tech-profile-prefix", kv_store_tech_profile_prefix=KV_STORE_TECH_PROFILE_PATH_PREFIX)
Chip Boling67b674a2019-02-08 11:42:18 -0600140
141 # Tech profile path in kv store
142 TECH_PROFILE_PATH = '{}/{}' # <technology>/<table_id>
143
144 # Tech profile instance path in kv store
145 # Format: <technology>/<table_id>/<uni_port_name>
146 TECH_PROFILE_INSTANCE_PATH = '{}/{}/{}'
147
148 # Tech-Profile JSON String Keys
149 NAME = 'name'
150 PROFILE_TYPE = 'profile_type'
151 VERSION = 'version'
152 NUM_GEM_PORTS = 'num_gem_ports'
153 INSTANCE_CONTROL = 'instance_control'
154 US_SCHEDULER = 'us_scheduler'
155 DS_SCHEDULER = 'ds_scheduler'
156 UPSTREAM_GEM_PORT_ATTRIBUTE_LIST = 'upstream_gem_port_attribute_list'
157 DOWNSTREAM_GEM_PORT_ATTRIBUTE_LIST = 'downstream_gem_port_attribute_list'
158 ONU = 'onu'
159 UNI = 'uni'
160 MAX_GEM_PAYLOAD_SIZE = 'max_gem_payload_size'
161 DIRECTION = 'direction'
162 ADDITIONAL_BW = 'additional_bw'
163 PRIORITY = 'priority'
164 Q_SCHED_POLICY = 'q_sched_policy'
165 WEIGHT = 'weight'
166 PBIT_MAP = 'pbit_map'
167 DISCARD_CONFIG = 'discard_config'
168 MAX_THRESHOLD = 'max_threshold'
169 MIN_THRESHOLD = 'min_threshold'
170 MAX_PROBABILITY = 'max_probability'
171 DISCARD_POLICY = 'discard_policy'
172 PRIORITY_Q = 'priority_q'
173 SCHEDULING_POLICY = 'scheduling_policy'
174 MAX_Q_SIZE = 'max_q_size'
175 AES_ENCRYPTION = 'aes_encryption'
176
177 def __init__(self, resource_mgr):
178 try:
179 self.args = registry('main').get_args()
180 self.resource_mgr = resource_mgr
Chip Boling67b674a2019-02-08 11:42:18 -0600181
182 if self.args.backend == 'etcd':
183 # KV store's IP Address and PORT
184 host, port = self.args.etcd.split(':', 1)
Matt Jeanneret6eb68172019-03-31 10:53:44 -0400185 self._kv_store = EtcdStore(
186 host, port, TechProfile.
187 KV_STORE_TECH_PROFILE_PATH_PREFIX)
Chip Boling67b674a2019-02-08 11:42:18 -0600188 elif self.args.backend == 'consul':
189 # KV store's IP Address and PORT
190 host, port = self.args.consul.split(':', 1)
Matt Jeanneret6eb68172019-03-31 10:53:44 -0400191 self._kv_store = ConsulStore(
192 host, port, TechProfile.
193 KV_STORE_TECH_PROFILE_PATH_PREFIX)
Chip Boling67b674a2019-02-08 11:42:18 -0600194
195 # self.tech_profile_instance_store = dict()
196 except Exception as e:
197 log.exception("exception-in-init")
198 raise Exception(e)
199
Chip Boling67b674a2019-02-08 11:42:18 -0600200 class DefaultTechProfile(object):
201 def __init__(self, name, **kwargs):
202 self.name = name
203 self.profile_type = kwargs[TechProfile.PROFILE_TYPE]
204 self.version = kwargs[TechProfile.VERSION]
205 self.num_gem_ports = kwargs[TechProfile.NUM_GEM_PORTS]
206 self.instance_control = kwargs[TechProfile.INSTANCE_CONTROL]
207 self.us_scheduler = kwargs[TechProfile.US_SCHEDULER]
208 self.ds_scheduler = kwargs[TechProfile.DS_SCHEDULER]
209 self.upstream_gem_port_attribute_list = kwargs[
210 TechProfile.UPSTREAM_GEM_PORT_ATTRIBUTE_LIST]
211 self.downstream_gem_port_attribute_list = kwargs[
212 TechProfile.DOWNSTREAM_GEM_PORT_ATTRIBUTE_LIST]
213
214 def to_json(self):
215 return json.dumps(self, default=lambda o: o.__dict__,
216 indent=4)
217
218 def get_tp_path(self, table_id, uni_port_name):
Matt Jeanneret6eb68172019-03-31 10:53:44 -0400219 path = TechProfile.TECH_PROFILE_INSTANCE_PATH.format(
Chip Boling67b674a2019-02-08 11:42:18 -0600220 self.resource_mgr.technology, table_id, uni_port_name)
Matt Jeanneret6eb68172019-03-31 10:53:44 -0400221 log.debug("constructed-tp-path", table_id=table_id, technology=self.resource_mgr.technology,
222 uni_port_name=uni_port_name, path=path)
223 return path
Chip Boling67b674a2019-02-08 11:42:18 -0600224
225 def create_tech_profile_instance(self, table_id, uni_port_name, intf_id):
226 tech_profile_instance = None
227 try:
228 # Get tech profile from kv store
229 tech_profile = self._get_tech_profile_from_kv_store(table_id)
230 path = self.get_tp_path(table_id, uni_port_name)
231
232 if tech_profile is not None:
233 tech_profile = self._get_tech_profile(tech_profile)
234 log.debug(
235 "Created-tech-profile-instance-with-values-from-kvstore")
236 else:
237 tech_profile = self._default_tech_profile()
238 log.debug(
239 "Created-tech-profile-instance-with-default-values")
240
241 tech_profile_instance = TechProfileInstance(
242 uni_port_name, tech_profile, self.resource_mgr, intf_id)
243 self._add_tech_profile_instance(path,
244 tech_profile_instance.to_json())
245 except Exception as e:
246 log.exception("Create-tech-profile-instance-failed", exception=e)
247
248 return tech_profile_instance
249
250 def get_tech_profile_instance(self, table_id, uni_port_name):
251 # path to fetch tech profile instance json from kv store
252 path = TechProfile.TECH_PROFILE_INSTANCE_PATH.format(
253 self.resource_mgr.technology, table_id, uni_port_name)
254
255 try:
Matt Jeanneret6eb68172019-03-31 10:53:44 -0400256 tech_profile_instance = self._kv_store[path]
Chip Boling67b674a2019-02-08 11:42:18 -0600257 log.debug("Tech-profile-instance-present-in-kvstore", path=path,
258 tech_profile_instance=tech_profile_instance)
259
260 # Parse JSON into an object with attributes corresponding to dict keys.
261 tech_profile_instance = json.loads(tech_profile_instance,
262 object_hook=lambda d:
263 namedtuple('tech_profile_instance',
Zack Williams84a71e92019-11-15 09:00:19 -0700264 list(d.keys()))(*list(d.values())))
Chip Boling67b674a2019-02-08 11:42:18 -0600265 log.debug("Tech-profile-instance-after-json-to-object-conversion", path=path,
266 tech_profile_instance=tech_profile_instance)
267 return tech_profile_instance
268 except BaseException as e:
269 log.debug("Tech-profile-instance-not-present-in-kvstore",
270 path=path, tech_profile_instance=None, exception=e)
271 return None
272
273 def delete_tech_profile_instance(self, tp_path):
274
275 try:
Matt Jeanneret6eb68172019-03-31 10:53:44 -0400276 del self._kv_store[tp_path]
Chip Boling67b674a2019-02-08 11:42:18 -0600277 log.debug("Delete-tech-profile-instance-success", path=tp_path)
278 return True
279 except Exception as e:
280 log.debug("Delete-tech-profile-instance-failed", path=tp_path,
281 exception=e)
282 return False
283
284 def _get_tech_profile_from_kv_store(self, table_id):
285 """
286 Get tech profile from kv store.
287
288 :param table_id: reference to get tech profile
289 :return: tech profile if present in kv store else None
290 """
291 # get tech profile from kv store
292 path = TechProfile.TECH_PROFILE_PATH.format(self.resource_mgr.technology,
293 table_id)
294 try:
Matt Jeanneret6eb68172019-03-31 10:53:44 -0400295 tech_profile = self._kv_store[path]
Chip Boling67b674a2019-02-08 11:42:18 -0600296 if tech_profile != '':
297 log.debug("Get-tech-profile-success", tech_profile=tech_profile)
298 return json.loads(tech_profile)
299 # return ast.literal_eval(tech_profile)
300 except KeyError as e:
301 log.info("Get-tech-profile-failed", exception=e)
302 return None
303
304 def _default_tech_profile(self):
305 # Default tech profile
306 upstream_gem_port_attribute_list = list()
307 downstream_gem_port_attribute_list = list()
308 for pbit in TechProfile.pbits:
309 upstream_gem_port_attribute_list.append(
310 GemPortAttribute(pbit_map=pbit,
311 discard_config=DiscardConfig()))
312 downstream_gem_port_attribute_list.append(
313 GemPortAttribute(pbit_map=pbit,
314 discard_config=DiscardConfig()))
315
316 return TechProfile.DefaultTechProfile(
317 TechProfile.DEFAULT_TECH_PROFILE_NAME,
318 profile_type=self.resource_mgr.technology,
319 version=TechProfile.DEFAULT_VERSION,
320 num_gem_ports=TechProfile.DEFAULT_GEMPORTS_COUNT,
321 instance_control=InstanceControl(),
322 us_scheduler=Scheduler(direction=Direction.UPSTREAM.name),
323 ds_scheduler=Scheduler(direction=Direction.DOWNSTREAM.name),
324 upstream_gem_port_attribute_list=upstream_gem_port_attribute_list,
325 downstream_gem_port_attribute_list=
326 downstream_gem_port_attribute_list)
327
328 @staticmethod
329 def _get_tech_profile(tech_profile):
330 # Tech profile fetched from kv store
331 instance_control = tech_profile[TechProfile.INSTANCE_CONTROL]
332 instance_control = InstanceControl(
333 onu=instance_control[TechProfile.ONU],
334 uni=instance_control[TechProfile.UNI],
335 max_gem_payload_size=instance_control[
336 TechProfile.MAX_GEM_PAYLOAD_SIZE])
337
338 us_scheduler = tech_profile[TechProfile.US_SCHEDULER]
339 us_scheduler = Scheduler(direction=us_scheduler[TechProfile.DIRECTION],
340 additional_bw=us_scheduler[
341 TechProfile.ADDITIONAL_BW],
342 priority=us_scheduler[TechProfile.PRIORITY],
343 weight=us_scheduler[TechProfile.WEIGHT],
344 q_sched_policy=us_scheduler[
345 TechProfile.Q_SCHED_POLICY])
346 ds_scheduler = tech_profile[TechProfile.DS_SCHEDULER]
347 ds_scheduler = Scheduler(direction=ds_scheduler[TechProfile.DIRECTION],
348 additional_bw=ds_scheduler[
349 TechProfile.ADDITIONAL_BW],
350 priority=ds_scheduler[TechProfile.PRIORITY],
351 weight=ds_scheduler[TechProfile.WEIGHT],
352 q_sched_policy=ds_scheduler[
353 TechProfile.Q_SCHED_POLICY])
354
355 upstream_gem_port_attribute_list = list()
356 downstream_gem_port_attribute_list = list()
357 us_gemport_attr_list = tech_profile[
358 TechProfile.UPSTREAM_GEM_PORT_ATTRIBUTE_LIST]
359 for i in range(len(us_gemport_attr_list)):
360 upstream_gem_port_attribute_list.append(
361 GemPortAttribute(pbit_map=us_gemport_attr_list[i][TechProfile.PBIT_MAP],
362 discard_config=DiscardConfig(
363 max_threshold=
364 us_gemport_attr_list[i][TechProfile.DISCARD_CONFIG][
365 TechProfile.MAX_THRESHOLD],
366 min_threshold=
367 us_gemport_attr_list[i][TechProfile.DISCARD_CONFIG][
368 TechProfile.MIN_THRESHOLD],
369 max_probability=
370 us_gemport_attr_list[i][TechProfile.DISCARD_CONFIG][
371 TechProfile.MAX_PROBABILITY]),
372 discard_policy=us_gemport_attr_list[i][
373 TechProfile.DISCARD_POLICY],
374 priority_q=us_gemport_attr_list[i][
375 TechProfile.PRIORITY_Q],
376 weight=us_gemport_attr_list[i][TechProfile.WEIGHT],
377 scheduling_policy=us_gemport_attr_list[i][
378 TechProfile.SCHEDULING_POLICY],
379 max_q_size=us_gemport_attr_list[i][
380 TechProfile.MAX_Q_SIZE],
381 aes_encryption=us_gemport_attr_list[i][
382 TechProfile.AES_ENCRYPTION]))
383
384 ds_gemport_attr_list = tech_profile[
385 TechProfile.DOWNSTREAM_GEM_PORT_ATTRIBUTE_LIST]
386 for i in range(len(ds_gemport_attr_list)):
387 downstream_gem_port_attribute_list.append(
388 GemPortAttribute(pbit_map=ds_gemport_attr_list[i][TechProfile.PBIT_MAP],
389 discard_config=DiscardConfig(
390 max_threshold=
391 ds_gemport_attr_list[i][TechProfile.DISCARD_CONFIG][
392 TechProfile.MAX_THRESHOLD],
393 min_threshold=
394 ds_gemport_attr_list[i][TechProfile.DISCARD_CONFIG][
395 TechProfile.MIN_THRESHOLD],
396 max_probability=
397 ds_gemport_attr_list[i][TechProfile.DISCARD_CONFIG][
398 TechProfile.MAX_PROBABILITY]),
399 discard_policy=ds_gemport_attr_list[i][
400 TechProfile.DISCARD_POLICY],
401 priority_q=ds_gemport_attr_list[i][
402 TechProfile.PRIORITY_Q],
403 weight=ds_gemport_attr_list[i][TechProfile.WEIGHT],
404 scheduling_policy=ds_gemport_attr_list[i][
405 TechProfile.SCHEDULING_POLICY],
406 max_q_size=ds_gemport_attr_list[i][
407 TechProfile.MAX_Q_SIZE],
408 aes_encryption=ds_gemport_attr_list[i][
409 TechProfile.AES_ENCRYPTION]))
410
411 return TechProfile.DefaultTechProfile(
412 tech_profile[TechProfile.NAME],
413 profile_type=tech_profile[TechProfile.PROFILE_TYPE],
414 version=tech_profile[TechProfile.VERSION],
415 num_gem_ports=tech_profile[TechProfile.NUM_GEM_PORTS],
416 instance_control=instance_control,
417 us_scheduler=us_scheduler,
418 ds_scheduler=ds_scheduler,
419 upstream_gem_port_attribute_list=upstream_gem_port_attribute_list,
420 downstream_gem_port_attribute_list=
421 downstream_gem_port_attribute_list)
422
423 def _add_tech_profile_instance(self, path, tech_profile_instance):
424 """
425 Add tech profile to kv store.
426
427 :param path: path to add tech profile
428 :param tech_profile_instance: tech profile instance need to be added
429 """
430 try:
Matt Jeanneret6eb68172019-03-31 10:53:44 -0400431 self._kv_store[path] = str(tech_profile_instance)
Chip Boling67b674a2019-02-08 11:42:18 -0600432 log.debug("Add-tech-profile-instance-success", path=path,
433 tech_profile_instance=tech_profile_instance)
434 return True
435 except BaseException as e:
436 log.exception("Add-tech-profile-instance-failed", path=path,
437 tech_profile_instance=tech_profile_instance,
438 exception=e)
439 return False
440
441 @staticmethod
442 def get_us_scheduler(tech_profile_instance):
443 # upstream scheduler
444 us_scheduler = openolt_pb2.Scheduler(
445 direction=TechProfile.get_parameter(
446 'direction', tech_profile_instance.us_scheduler.
447 direction),
448 additional_bw=TechProfile.get_parameter(
449 'additional_bw', tech_profile_instance.
450 us_scheduler.additional_bw),
451 priority=tech_profile_instance.us_scheduler.priority,
452 weight=tech_profile_instance.us_scheduler.weight,
453 sched_policy=TechProfile.get_parameter(
454 'sched_policy', tech_profile_instance.
455 us_scheduler.q_sched_policy))
456
457 return us_scheduler
458
459 @staticmethod
460 def get_ds_scheduler(tech_profile_instance):
461 ds_scheduler = openolt_pb2.Scheduler(
462 direction=TechProfile.get_parameter(
463 'direction', tech_profile_instance.ds_scheduler.
464 direction),
465 additional_bw=TechProfile.get_parameter(
466 'additional_bw', tech_profile_instance.
467 ds_scheduler.additional_bw),
468 priority=tech_profile_instance.ds_scheduler.priority,
469 weight=tech_profile_instance.ds_scheduler.weight,
470 sched_policy=TechProfile.get_parameter(
471 'sched_policy', tech_profile_instance.ds_scheduler.
472 q_sched_policy))
473
474 return ds_scheduler
475
476 @staticmethod
477 def get_tconts(tech_profile_instance, us_scheduler=None, ds_scheduler=None):
478 if us_scheduler is None:
479 us_scheduler = TechProfile.get_us_scheduler(tech_profile_instance)
480 if ds_scheduler is None:
481 ds_scheduler = TechProfile.get_ds_scheduler(tech_profile_instance)
482
483 tconts = [openolt_pb2.Tcont(direction=TechProfile.get_parameter(
484 'direction',
485 tech_profile_instance.
486 us_scheduler.direction),
487 alloc_id=tech_profile_instance.
488 us_scheduler.alloc_id,
489 scheduler=us_scheduler),
490 openolt_pb2.Tcont(direction=TechProfile.get_parameter(
491 'direction',
492 tech_profile_instance.
493 ds_scheduler.direction),
494 alloc_id=tech_profile_instance.
495 ds_scheduler.alloc_id,
496 scheduler=ds_scheduler)]
497
498 return tconts
499
500 @staticmethod
501 def get_parameter(param_type, param_value):
502 parameter = None
503 try:
504 if param_type == 'direction':
505 for direction in openolt_pb2.Direction.keys():
506 if param_value == direction:
507 parameter = direction
508 elif param_type == 'discard_policy':
509 for discard_policy in openolt_pb2.DiscardPolicy.keys():
510 if param_value == discard_policy:
511 parameter = discard_policy
512 elif param_type == 'sched_policy':
513 for sched_policy in openolt_pb2.SchedulingPolicy.keys():
514 if param_value == sched_policy:
515 parameter = sched_policy
516 elif param_type == 'additional_bw':
517 for bw_component in openolt_pb2.AdditionalBW.keys():
518 if param_value == bw_component:
519 parameter = bw_component
520 except BaseException as e:
521 log.exception(exception=e)
522 return parameter
523
524
525class TechProfileInstance(object):
526 def __init__(self, subscriber_identifier, tech_profile, resource_mgr,
527 intf_id, num_of_tconts=1):
528 if tech_profile is not None:
529 self.subscriber_identifier = subscriber_identifier
530 self.num_of_tconts = num_of_tconts
531 self.num_of_gem_ports = tech_profile.num_gem_ports
532 self.name = tech_profile.name
533 self.profile_type = tech_profile.profile_type
534 self.version = tech_profile.version
535 self.instance_control = tech_profile.instance_control
536
537 # TODO: Fixed num_of_tconts to 1 per TP Instance.
538 # This may change in future
539 assert (num_of_tconts == 1)
540 # Get alloc id and gemport id using resource manager
541 alloc_id = resource_mgr.get_resource_id(intf_id,
542 'ALLOC_ID',
543 num_of_tconts)
544 gem_ports = resource_mgr.get_resource_id(intf_id,
545 'GEMPORT_ID',
546 self.num_of_gem_ports)
547
548 gemport_list = list()
549 if isinstance(gem_ports, int):
550 gemport_list.append(gem_ports)
551 elif isinstance(gem_ports, list):
552 for gem in gem_ports:
553 gemport_list.append(gem)
554 else:
555 raise Exception("invalid-type")
556
557 self.us_scheduler = TechProfileInstance.IScheduler(
558 alloc_id, tech_profile.us_scheduler)
559 self.ds_scheduler = TechProfileInstance.IScheduler(
560 alloc_id, tech_profile.ds_scheduler)
561
562 self.upstream_gem_port_attribute_list = list()
563 self.downstream_gem_port_attribute_list = list()
564 for i in range(self.num_of_gem_ports):
565 self.upstream_gem_port_attribute_list.append(
566 TechProfileInstance.IGemPortAttribute(
567 gemport_list[i],
568 tech_profile.upstream_gem_port_attribute_list[
569 i]))
570 self.downstream_gem_port_attribute_list.append(
571 TechProfileInstance.IGemPortAttribute(
572 gemport_list[i],
573 tech_profile.downstream_gem_port_attribute_list[
574 i]))
575
576 class IScheduler(Scheduler):
577 def __init__(self, alloc_id, scheduler):
578 super(TechProfileInstance.IScheduler, self).__init__(
579 scheduler.direction, scheduler.additional_bw,
580 scheduler.priority,
581 scheduler.weight, scheduler.q_sched_policy)
582 self.alloc_id = alloc_id
583
584 class IGemPortAttribute(GemPortAttribute):
585 def __init__(self, gemport_id, gem_port_attribute):
586 super(TechProfileInstance.IGemPortAttribute, self).__init__(
587 gem_port_attribute.pbit_map, gem_port_attribute.discard_config,
588 gem_port_attribute.aes_encryption,
589 gem_port_attribute.scheduling_policy,
590 gem_port_attribute.priority_q, gem_port_attribute.weight,
591 gem_port_attribute.max_q_size,
592 gem_port_attribute.discard_policy)
593 self.gemport_id = gemport_id
594
595 def to_json(self):
596 return json.dumps(self, default=lambda o: o.__dict__,
597 indent=4)