diff options
Diffstat (limited to 'scripts/automation/trex_control_plane/stl')
3 files changed, 74 insertions, 133 deletions
diff --git a/scripts/automation/trex_control_plane/stl/rpc_defaults.yaml b/scripts/automation/trex_control_plane/stl/rpc_defaults.yaml deleted file mode 100644 index ad814b3e..00000000 --- a/scripts/automation/trex_control_plane/stl/rpc_defaults.yaml +++ /dev/null @@ -1,124 +0,0 @@ -############################################################## -#### TRex RPC stream list default values #### -############################################################## - -# this document is based on TRex RPC server spec and its fields: -# http://trex-tgn.cisco.com/trex/doc/trex_rpc_server_spec.html - -### HOW TO READ THIS FILE -# 1. Each key represents an object type -# 2. Each value can be either a value field or another object -# 2.1. If a value field, read as: -# + type: type of field -# + has_default: if the value has any default -# + default: the default value (Only appears if has_default field is 'YES') -# 2.2. If an object type, jump to corresponding object key. -# 3. If an object has more than one instance type, another layer with the type shall be added. -# For example, 'mode' object has 3 types: 'continuous', 'single_burst', 'multi_burst' -# So, 3 mode objects will be defined, named: -# - mode['continuous'] -# - mode['single_burst'] -# - mode['multi_burst'] -# In this case, there's no default for the 'type' field on the object -# 4. Some values has 'multiply' property attached. -# In such case, the loaded value will be multiplied by the multiplier -# For example, if the mode's 'pps' field value is 10, and its multiplier is 5, -# the loaded pps value will be 10*5=50 -# 5. Any object type must be listed by the user, even if all its field are defaults. -# The most basic option would be to declare the object with "[]", which stands for empty object in YAML syntax. - - -stream: - enabled: - type: boolean - has_default: YES - default: True - self_start: - type: boolean - has_default: YES - default: True - isg: - type: [int, double, string] - has_default: YES - default: 0.0 - next_stream_id: - type: string # string to allow naming binding - has_default: YES - default: -1 # no next streams - packet: - type: object - mode: - type: object - vm: - type: object - rx_stats: - type: object - -packet: - binary: - type: [array,string] - has_default: NO - meta: - type: string - has_default: YES - default: "" - -mode: - continuous: - pps: - type: [int, double] - has_default: NO - multiply: YES - single_burst: - pps: - type: [int, double] - has_default: NO - multiply: YES - total_pkts: - type: int - has_default: NO - multi_burst: - pps: - type: [int, double] - has_default: NO - multiply: YES - pkts_per_burst: - type: int - has_default: NO - ibg: - type: [int, double, string] - has_default: YES - default: 100.0 - count: - type: int - has_default: YES - default: 0 # loop forever - -rx_stats: - enabled: - type: boolean - has_default: YES - default: False - stream_id: - type: string - has_default: YES - default: False # use related stream_id - seq_enabled: - type: boolean - has_default: YES - default: False - latency_enabled: - type: boolean - has_default: YES - default: False - -vm: - instructions: - type: array - has_default: YES - default: [] - split_by_var: - type: string - has_default: YES - default: "" - diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_port.py b/scripts/automation/trex_control_plane/stl/trex_stl_port.py index 8923d3d6..b2cf1c90 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_port.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_port.py @@ -52,6 +52,8 @@ class Port(object): self.port_stats = trex_stl_stats.CPortStats(self) + self.next_available_id = 1 + def err(self, msg): return RC_ERR("port {0} : {1}".format(self.port_id, msg)) @@ -130,6 +132,8 @@ class Port(object): # TODO: handle syncing the streams into stream_db + self.next_available_id = rc.data()['max_stream_id'] + return self.ok() @@ -139,6 +143,12 @@ class Port(object): return ((self.state == self.STATE_IDLE) or (self.state == self.STATE_STREAMS)) + def __allocate_stream_id (self): + id = self.next_available_id + self.next_available_id += 1 + return id + + # add streams def add_streams (self, streams_list): @@ -148,8 +158,33 @@ class Port(object): if not self.is_port_writable(): return self.err("Please stop port before attempting to add streams") + # listify + streams_list = streams_list if isinstance(streams_list, list) else [streams_list] + + lookup = {} + + # allocate IDs + for stream in streams_list: + if stream.get_id() == None: + stream.set_id(self.__allocate_stream_id()) + + lookup[stream.get_name()] = stream.get_id() + + # resolve names + for stream in streams_list: + next_id = -1 + + next = stream.get_next() + if next: + if not next in lookup: + return self.err("stream dependency error - unable to find '{0}'".format(next)) + next_id = lookup[next] + + stream.fields['next_stream_id'] = next_id + + batch = [] - for stream in (streams_list if isinstance(streams_list, list) else [streams_list]): + for stream in streams_list: params = {"handler": self.handler, "port_id": self.port_id, diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_streams.py b/scripts/automation/trex_control_plane/stl/trex_stl_streams.py index d5cba9e2..798b2f67 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_streams.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_streams.py @@ -11,6 +11,11 @@ from dpkt import pcap import random import yaml import base64 +import string + +def random_name (l): + return ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(l)) + # base class for TX mode class STLTXMode(object): @@ -86,13 +91,14 @@ class STLTXMultiBurst(STLTXMode): class STLStream(object): def __init__ (self, + name = random_name(8), packet = None, mode = STLTXCont(1), enabled = True, self_start = True, isg = 0.0, rx_stats = None, - next_stream_id = -1, + next = None, stream_id = None): # type checking @@ -111,21 +117,21 @@ class STLStream(object): if not isinstance(isg, (int, float)): raise STLArgumentError('isg', isg) - if (type(mode) == STLTXCont) and (next_stream_id != -1): + if (type(mode) == STLTXCont) and (next != None): raise STLError("continuous stream cannot have a next stream ID") - self.fields = {} + # tag for the stream and next - can be anything + self.name = name + self.next = next + self.set_id(stream_id) - # use a random 31 bit for ID - self.fields['stream_id'] = stream_id if stream_id is not None else random.getrandbits(31) + self.fields = {} # basic fields self.fields['enabled'] = enabled self.fields['self_start'] = self_start self.fields['isg'] = isg - self.fields['next_stream_id'] = next_stream_id - # mode self.fields['mode'] = mode.to_json() @@ -153,8 +159,20 @@ class STLStream(object): return self.fields def get_id (self): - return self.fields['stream_id'] + return self.id + + def set_id (self, id): + self.id = id + + def get_name (self): + return self.name + def get_next (self): + return self.next + + + def to_yaml (self): + fields = dict(stream.fields) @staticmethod @@ -228,3 +246,15 @@ class STLStream(object): return streams + +class STLYAMLLoader(object): + def __init__ (self, yaml_file): + self.yaml_file = yaml_file + + def load (self): + with open(self.yaml_file, 'r') as f: + yaml_str = f.read() + objects = yaml.load(yaml_str) + + for object in objects: + pass |