blob: 6055b0bdd265d0de176e27f34a7559662d4c9cf5 [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
Girish Gowdru841708f2019-02-08 04:29:48 -080025from voltha.protos import tech_profile_pb2
Shad Ansarie9c2db82019-01-22 15:05:36 -080026
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
Girish Gowdru841708f2019-02-08 04:29:48 -080068 DEFAULT_Q_SCHED_POLICY = 'Hybrid'
Shad Ansarie9c2db82019-01-22 15:05:36 -080069
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.
Girish Gowdru841708f2019-02-08 04:29:48 -0800176 KV_STORE_TECH_PROFILE_PATH_PREFIX)
Shad Ansarie9c2db82019-01-22 15:05:36 -0800177 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.
Girish Gowdru841708f2019-02-08 04:29:48 -0800182 KV_STORE_TECH_PROFILE_PATH_PREFIX)
Shad Ansarie9c2db82019-01-22 15:05:36 -0800183
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:
Girish Gowdru841708f2019-02-08 04:29:48 -0800223 # Create a default Tech-Profile.
224 # The default profile is a 1 TCONT, 1 GEM port model.
Shad Ansarie9c2db82019-01-22 15:05:36 -0800225 tech_profile = self._default_tech_profile()
226 log.debug(
227 "Created-tech-profile-instance-with-default-values")
228
229 tech_profile_instance = TechProfileInstance(
230 uni_port_name, tech_profile, self.resource_mgr, intf_id)
231 self._add_tech_profile_instance(path,
232 tech_profile_instance.to_json())
233 except Exception as e:
234 log.exception("Create-tech-profile-instance-failed", exception=e)
235
236 return tech_profile_instance
237
238 def get_tech_profile_instance(self, table_id, uni_port_name):
239 # path to fetch tech profile instance json from kv store
240 path = TechProfile.TECH_PROFILE_INSTANCE_PATH.format(
241 self.resource_mgr.technology, table_id, uni_port_name)
242
243 try:
244 tech_profile_instance = self._kv_store[path]
245 log.debug("Tech-profile-instance-present-in-kvstore", path=path,
246 tech_profile_instance=tech_profile_instance)
247
248 # Parse JSON into an object with attributes corresponding to dict keys.
249 tech_profile_instance = json.loads(tech_profile_instance,
250 object_hook=lambda d:
251 namedtuple('tech_profile_instance',
252 d.keys())(*d.values()))
253 log.debug("Tech-profile-instance-after-json-to-object-conversion", path=path,
254 tech_profile_instance=tech_profile_instance)
255 return tech_profile_instance
256 except BaseException as e:
257 log.debug("Tech-profile-instance-not-present-in-kvstore",
258 path=path, tech_profile_instance=None, exception=e)
259 return None
260
261 def delete_tech_profile_instance(self, tp_path):
262
263 try:
264 del self._kv_store[tp_path]
265 log.debug("Delete-tech-profile-instance-success", path=tp_path)
266 return True
267 except Exception as e:
268 log.debug("Delete-tech-profile-instance-failed", path=tp_path,
269 exception=e)
270 return False
271
272 def _get_tech_profile_from_kv_store(self, table_id):
273 """
274 Get tech profile from kv store.
275
276 :param table_id: reference to get tech profile
277 :return: tech profile if present in kv store else None
278 """
279 # get tech profile from kv store
280 path = TechProfile.TECH_PROFILE_PATH.format(self.resource_mgr.technology,
281 table_id)
282 try:
283 tech_profile = self._kv_store[path]
284 if tech_profile != '':
285 log.debug("Get-tech-profile-success", tech_profile=tech_profile)
286 return json.loads(tech_profile)
287 # return ast.literal_eval(tech_profile)
288 except KeyError as e:
289 log.info("Get-tech-profile-failed", exception=e)
290 return None
291
292 def _default_tech_profile(self):
293 # Default tech profile
294 upstream_gem_port_attribute_list = list()
295 downstream_gem_port_attribute_list = list()
296 for pbit in TechProfile.pbits:
297 upstream_gem_port_attribute_list.append(
298 GemPortAttribute(pbit_map=pbit,
299 discard_config=DiscardConfig()))
300 downstream_gem_port_attribute_list.append(
301 GemPortAttribute(pbit_map=pbit,
302 discard_config=DiscardConfig()))
303
304 return TechProfile.DefaultTechProfile(
305 TechProfile.DEFAULT_TECH_PROFILE_NAME,
306 profile_type=self.resource_mgr.technology,
307 version=TechProfile.DEFAULT_VERSION,
308 num_gem_ports=TechProfile.DEFAULT_GEMPORTS_COUNT,
309 instance_control=InstanceControl(),
310 us_scheduler=Scheduler(direction=Direction.UPSTREAM.name),
311 ds_scheduler=Scheduler(direction=Direction.DOWNSTREAM.name),
312 upstream_gem_port_attribute_list=upstream_gem_port_attribute_list,
313 downstream_gem_port_attribute_list=
314 downstream_gem_port_attribute_list)
315
316 @staticmethod
317 def _get_tech_profile(tech_profile):
318 # Tech profile fetched from kv store
319 instance_control = tech_profile[TechProfile.INSTANCE_CONTROL]
320 instance_control = InstanceControl(
321 onu=instance_control[TechProfile.ONU],
322 uni=instance_control[TechProfile.UNI],
323 max_gem_payload_size=instance_control[
324 TechProfile.MAX_GEM_PAYLOAD_SIZE])
325
326 us_scheduler = tech_profile[TechProfile.US_SCHEDULER]
327 us_scheduler = Scheduler(direction=us_scheduler[TechProfile.DIRECTION],
328 additional_bw=us_scheduler[
329 TechProfile.ADDITIONAL_BW],
330 priority=us_scheduler[TechProfile.PRIORITY],
331 weight=us_scheduler[TechProfile.WEIGHT],
332 q_sched_policy=us_scheduler[
333 TechProfile.Q_SCHED_POLICY])
334 ds_scheduler = tech_profile[TechProfile.DS_SCHEDULER]
335 ds_scheduler = Scheduler(direction=ds_scheduler[TechProfile.DIRECTION],
336 additional_bw=ds_scheduler[
337 TechProfile.ADDITIONAL_BW],
338 priority=ds_scheduler[TechProfile.PRIORITY],
339 weight=ds_scheduler[TechProfile.WEIGHT],
340 q_sched_policy=ds_scheduler[
341 TechProfile.Q_SCHED_POLICY])
342
343 upstream_gem_port_attribute_list = list()
344 downstream_gem_port_attribute_list = list()
345 us_gemport_attr_list = tech_profile[
346 TechProfile.UPSTREAM_GEM_PORT_ATTRIBUTE_LIST]
347 for i in range(len(us_gemport_attr_list)):
348 upstream_gem_port_attribute_list.append(
349 GemPortAttribute(pbit_map=us_gemport_attr_list[i][TechProfile.PBIT_MAP],
350 discard_config=DiscardConfig(
351 max_threshold=
352 us_gemport_attr_list[i][TechProfile.DISCARD_CONFIG][
353 TechProfile.MAX_THRESHOLD],
354 min_threshold=
355 us_gemport_attr_list[i][TechProfile.DISCARD_CONFIG][
356 TechProfile.MIN_THRESHOLD],
357 max_probability=
358 us_gemport_attr_list[i][TechProfile.DISCARD_CONFIG][
359 TechProfile.MAX_PROBABILITY]),
360 discard_policy=us_gemport_attr_list[i][
361 TechProfile.DISCARD_POLICY],
362 priority_q=us_gemport_attr_list[i][
363 TechProfile.PRIORITY_Q],
364 weight=us_gemport_attr_list[i][TechProfile.WEIGHT],
365 scheduling_policy=us_gemport_attr_list[i][
366 TechProfile.SCHEDULING_POLICY],
367 max_q_size=us_gemport_attr_list[i][
368 TechProfile.MAX_Q_SIZE],
369 aes_encryption=us_gemport_attr_list[i][
370 TechProfile.AES_ENCRYPTION]))
371
372 ds_gemport_attr_list = tech_profile[
373 TechProfile.DOWNSTREAM_GEM_PORT_ATTRIBUTE_LIST]
374 for i in range(len(ds_gemport_attr_list)):
375 downstream_gem_port_attribute_list.append(
376 GemPortAttribute(pbit_map=ds_gemport_attr_list[i][TechProfile.PBIT_MAP],
377 discard_config=DiscardConfig(
378 max_threshold=
379 ds_gemport_attr_list[i][TechProfile.DISCARD_CONFIG][
380 TechProfile.MAX_THRESHOLD],
381 min_threshold=
382 ds_gemport_attr_list[i][TechProfile.DISCARD_CONFIG][
383 TechProfile.MIN_THRESHOLD],
384 max_probability=
385 ds_gemport_attr_list[i][TechProfile.DISCARD_CONFIG][
386 TechProfile.MAX_PROBABILITY]),
387 discard_policy=ds_gemport_attr_list[i][
388 TechProfile.DISCARD_POLICY],
389 priority_q=ds_gemport_attr_list[i][
390 TechProfile.PRIORITY_Q],
391 weight=ds_gemport_attr_list[i][TechProfile.WEIGHT],
392 scheduling_policy=ds_gemport_attr_list[i][
393 TechProfile.SCHEDULING_POLICY],
394 max_q_size=ds_gemport_attr_list[i][
395 TechProfile.MAX_Q_SIZE],
396 aes_encryption=ds_gemport_attr_list[i][
397 TechProfile.AES_ENCRYPTION]))
398
399 return TechProfile.DefaultTechProfile(
400 tech_profile[TechProfile.NAME],
401 profile_type=tech_profile[TechProfile.PROFILE_TYPE],
402 version=tech_profile[TechProfile.VERSION],
403 num_gem_ports=tech_profile[TechProfile.NUM_GEM_PORTS],
404 instance_control=instance_control,
405 us_scheduler=us_scheduler,
406 ds_scheduler=ds_scheduler,
407 upstream_gem_port_attribute_list=upstream_gem_port_attribute_list,
408 downstream_gem_port_attribute_list=
409 downstream_gem_port_attribute_list)
410
411 def _add_tech_profile_instance(self, path, tech_profile_instance):
412 """
413 Add tech profile to kv store.
414
415 :param path: path to add tech profile
416 :param tech_profile_instance: tech profile instance need to be added
417 """
418 try:
419 self._kv_store[path] = str(tech_profile_instance)
420 log.debug("Add-tech-profile-instance-success", path=path,
421 tech_profile_instance=tech_profile_instance)
422 return True
423 except BaseException as e:
424 log.exception("Add-tech-profile-instance-failed", path=path,
425 tech_profile_instance=tech_profile_instance,
426 exception=e)
427 return False
428
429 @staticmethod
430 def get_us_scheduler(tech_profile_instance):
431 # upstream scheduler
Girish Gowdru841708f2019-02-08 04:29:48 -0800432 us_scheduler = tech_profile_pb2.SchedulerConfig(
Shad Ansarie9c2db82019-01-22 15:05:36 -0800433 direction=TechProfile.get_parameter(
434 'direction', tech_profile_instance.us_scheduler.
435 direction),
436 additional_bw=TechProfile.get_parameter(
437 'additional_bw', tech_profile_instance.
438 us_scheduler.additional_bw),
439 priority=tech_profile_instance.us_scheduler.priority,
440 weight=tech_profile_instance.us_scheduler.weight,
441 sched_policy=TechProfile.get_parameter(
442 'sched_policy', tech_profile_instance.
443 us_scheduler.q_sched_policy))
444
445 return us_scheduler
446
447 @staticmethod
448 def get_ds_scheduler(tech_profile_instance):
Girish Gowdru841708f2019-02-08 04:29:48 -0800449 ds_scheduler = tech_profile_pb2.SchedulerConfig(
Shad Ansarie9c2db82019-01-22 15:05:36 -0800450 direction=TechProfile.get_parameter(
451 'direction', tech_profile_instance.ds_scheduler.
452 direction),
453 additional_bw=TechProfile.get_parameter(
454 'additional_bw', tech_profile_instance.
455 ds_scheduler.additional_bw),
456 priority=tech_profile_instance.ds_scheduler.priority,
457 weight=tech_profile_instance.ds_scheduler.weight,
458 sched_policy=TechProfile.get_parameter(
459 'sched_policy', tech_profile_instance.ds_scheduler.
460 q_sched_policy))
461
462 return ds_scheduler
463
464 @staticmethod
Girish Gowdru841708f2019-02-08 04:29:48 -0800465 def get_traffic_scheds(tech_profile_instance, us_scheduler=None, ds_scheduler=None):
Shad Ansarie9c2db82019-01-22 15:05:36 -0800466 if us_scheduler is None:
467 us_scheduler = TechProfile.get_us_scheduler(tech_profile_instance)
468 if ds_scheduler is None:
469 ds_scheduler = TechProfile.get_ds_scheduler(tech_profile_instance)
470
Girish Gowdru841708f2019-02-08 04:29:48 -0800471 tconts = [tech_profile_pb2.TrafficScheduler(direction=TechProfile.get_parameter(
Shad Ansarie9c2db82019-01-22 15:05:36 -0800472 'direction',
473 tech_profile_instance.
474 us_scheduler.direction),
475 alloc_id=tech_profile_instance.
476 us_scheduler.alloc_id,
477 scheduler=us_scheduler),
Girish Gowdru841708f2019-02-08 04:29:48 -0800478 tech_profile_pb2.TrafficScheduler(direction=TechProfile.get_parameter(
Shad Ansarie9c2db82019-01-22 15:05:36 -0800479 'direction',
480 tech_profile_instance.
481 ds_scheduler.direction),
482 alloc_id=tech_profile_instance.
483 ds_scheduler.alloc_id,
484 scheduler=ds_scheduler)]
485
486 return tconts
487
488 @staticmethod
Girish Gowdru841708f2019-02-08 04:29:48 -0800489 def get_traffic_queues(tech_profile_instance):
490 gemports = list()
491 # Upstream Gemports
492 for i in range(len(tech_profile_instance.
493 upstream_gem_port_attribute_list)):
494 gemports.append(tech_profile_pb2.TrafficQueue(
495 direction=TechProfile.get_parameter('direction',
496 tech_profile_instance.
497 us_scheduler.direction),
498 gemport_id=tech_profile_instance.
499 upstream_gem_port_attribute_list[i].gemport_id,
500 pbit_map=tech_profile_instance.
501 upstream_gem_port_attribute_list[i].pbit_map,
502 aes_encryption=ast.literal_eval(tech_profile_instance.
503 upstream_gem_port_attribute_list[i].aes_encryption),
504 sched_policy=TechProfile.get_parameter(
505 'sched_policy', tech_profile_instance.
506 upstream_gem_port_attribute_list[i].
507 scheduling_policy),
508 priority=tech_profile_instance.
509 upstream_gem_port_attribute_list[i].priority_q,
510 weight=tech_profile_instance.
511 upstream_gem_port_attribute_list[i].weight,
512 discard_policy=TechProfile.get_parameter(
513 'discard_policy', tech_profile_instance.
514 upstream_gem_port_attribute_list[i].
515 discard_policy)))
516
517 # Downstream Gemports
518 for i in range(len(tech_profile_instance.
519 downstream_gem_port_attribute_list)):
520 gemports.append(tech_profile_pb2.TrafficQueue(
521 direction=TechProfile.get_parameter('direction',
522 tech_profile_instance.
523 ds_scheduler.direction),
524 gemport_id=tech_profile_instance.
525 downstream_gem_port_attribute_list[i].gemport_id,
526 pbit_map=tech_profile_instance.
527 downstream_gem_port_attribute_list[i].pbit_map,
528 aes_encryption=ast.literal_eval(tech_profile_instance.
529 downstream_gem_port_attribute_list[i].aes_encryption),
530 sched_policy=TechProfile.get_parameter(
531 'sched_policy', tech_profile_instance.
532 downstream_gem_port_attribute_list[i].
533 scheduling_policy),
534 priority=tech_profile_instance.
535 downstream_gem_port_attribute_list[i].priority_q,
536 weight=tech_profile_instance.
537 downstream_gem_port_attribute_list[i].weight,
538 discard_policy=TechProfile.get_parameter(
539 'discard_policy', tech_profile_instance.
540 downstream_gem_port_attribute_list[i].
541 discard_policy)))
542 return gemports
543
544 @staticmethod
545 def get_us_traffic_scheduler(tech_profile_instance):
546 us_scheduler = TechProfile.get_us_scheduler(tech_profile_instance)
547 return tech_profile_pb2.TrafficScheduler(direction=TechProfile.get_parameter(
548 'direction',
549 us_scheduler.direction),
550 alloc_id=us_scheduler.alloc_id,
551 scheduler=us_scheduler)
552
553 @staticmethod
Shad Ansarie9c2db82019-01-22 15:05:36 -0800554 def get_parameter(param_type, param_value):
555 parameter = None
556 try:
557 if param_type == 'direction':
Girish Gowdru841708f2019-02-08 04:29:48 -0800558 for direction in tech_profile_pb2.Direction.keys():
Shad Ansarie9c2db82019-01-22 15:05:36 -0800559 if param_value == direction:
560 parameter = direction
561 elif param_type == 'discard_policy':
Girish Gowdru841708f2019-02-08 04:29:48 -0800562 for discard_policy in tech_profile_pb2.DiscardPolicy.keys():
Shad Ansarie9c2db82019-01-22 15:05:36 -0800563 if param_value == discard_policy:
564 parameter = discard_policy
Girish Gowdru841708f2019-02-08 04:29:48 -0800565 elif param_type == 'q_sched_policy':
566 for sched_policy in tech_profile_pb2.SchedulingPolicy.keys():
Shad Ansarie9c2db82019-01-22 15:05:36 -0800567 if param_value == sched_policy:
568 parameter = sched_policy
569 elif param_type == 'additional_bw':
Girish Gowdru841708f2019-02-08 04:29:48 -0800570 for bw_component in tech_profile_pb2.AdditionalBW.keys():
Shad Ansarie9c2db82019-01-22 15:05:36 -0800571 if param_value == bw_component:
572 parameter = bw_component
573 except BaseException as e:
574 log.exception(exception=e)
575 return parameter
576
577
578class TechProfileInstance(object):
579 def __init__(self, subscriber_identifier, tech_profile, resource_mgr,
Girish Gowdru841708f2019-02-08 04:29:48 -0800580 intf_id):
Shad Ansarie9c2db82019-01-22 15:05:36 -0800581 if tech_profile is not None:
582 self.subscriber_identifier = subscriber_identifier
Shad Ansarie9c2db82019-01-22 15:05:36 -0800583
Shad Ansarie9c2db82019-01-22 15:05:36 -0800584 # Get alloc id and gemport id using resource manager
585 alloc_id = resource_mgr.get_resource_id(intf_id,
586 'ALLOC_ID',
Girish Gowdru841708f2019-02-08 04:29:48 -0800587 1)
Shad Ansarie9c2db82019-01-22 15:05:36 -0800588 gem_ports = resource_mgr.get_resource_id(intf_id,
589 'GEMPORT_ID',
Girish Gowdru841708f2019-02-08 04:29:48 -0800590 tech_profile.num_gem_ports)
Shad Ansarie9c2db82019-01-22 15:05:36 -0800591
592 gemport_list = list()
593 if isinstance(gem_ports, int):
594 gemport_list.append(gem_ports)
595 elif isinstance(gem_ports, list):
596 for gem in gem_ports:
597 gemport_list.append(gem)
598 else:
599 raise Exception("invalid-type")
600
601 self.us_scheduler = TechProfileInstance.IScheduler(
602 alloc_id, tech_profile.us_scheduler)
603 self.ds_scheduler = TechProfileInstance.IScheduler(
604 alloc_id, tech_profile.ds_scheduler)
605
606 self.upstream_gem_port_attribute_list = list()
607 self.downstream_gem_port_attribute_list = list()
Girish Gowdru841708f2019-02-08 04:29:48 -0800608 for i in range(tech_profile.num_gem_ports):
Shad Ansarie9c2db82019-01-22 15:05:36 -0800609 self.upstream_gem_port_attribute_list.append(
610 TechProfileInstance.IGemPortAttribute(
611 gemport_list[i],
612 tech_profile.upstream_gem_port_attribute_list[
613 i]))
614 self.downstream_gem_port_attribute_list.append(
615 TechProfileInstance.IGemPortAttribute(
616 gemport_list[i],
617 tech_profile.downstream_gem_port_attribute_list[
618 i]))
619
620 class IScheduler(Scheduler):
621 def __init__(self, alloc_id, scheduler):
622 super(TechProfileInstance.IScheduler, self).__init__(
623 scheduler.direction, scheduler.additional_bw,
624 scheduler.priority,
625 scheduler.weight, scheduler.q_sched_policy)
626 self.alloc_id = alloc_id
627
628 class IGemPortAttribute(GemPortAttribute):
629 def __init__(self, gemport_id, gem_port_attribute):
630 super(TechProfileInstance.IGemPortAttribute, self).__init__(
631 gem_port_attribute.pbit_map, gem_port_attribute.discard_config,
632 gem_port_attribute.aes_encryption,
633 gem_port_attribute.scheduling_policy,
634 gem_port_attribute.priority_q, gem_port_attribute.weight,
635 gem_port_attribute.max_q_size,
636 gem_port_attribute.discard_policy)
637 self.gemport_id = gemport_id
638
639 def to_json(self):
640 return json.dumps(self, default=lambda o: o.__dict__,
641 indent=4)