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