summaryrefslogtreecommitdiffstats
path: root/scripts/automation/trex_control_plane
diff options
context:
space:
mode:
authorHanoh Haim <hhaim@cisco.com>2016-02-24 14:55:59 +0200
committerHanoh Haim <hhaim@cisco.com>2016-02-24 14:55:59 +0200
commit5a844c9d72411435842e5a0674c6fdc04e5d4e84 (patch)
treedc2738fe0638ac0ed856c70564bc7096bb33868e /scripts/automation/trex_control_plane
parent9e616d8eecaefbf538174328edfce8fd96336ce6 (diff)
parent3eb4f868ef5bc728a46c8012c914f6a9381f4cdb (diff)
Merge GARP example
Diffstat (limited to 'scripts/automation/trex_control_plane')
-rw-r--r--scripts/automation/trex_control_plane/stl/examples/stl_bi_dir_flows.py4
-rw-r--r--scripts/automation/trex_control_plane/stl/examples/stl_run_udp_simple.py4
-rwxr-xr-xscripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_hltapi.py40
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py95
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_sim.py27
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py3
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py106
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_types.py4
8 files changed, 185 insertions, 98 deletions
diff --git a/scripts/automation/trex_control_plane/stl/examples/stl_bi_dir_flows.py b/scripts/automation/trex_control_plane/stl/examples/stl_bi_dir_flows.py
index 2382f2f4..7e90e264 100644
--- a/scripts/automation/trex_control_plane/stl/examples/stl_bi_dir_flows.py
+++ b/scripts/automation/trex_control_plane/stl/examples/stl_bi_dir_flows.py
@@ -20,11 +20,11 @@ def create_pkt (size, direction):
vm = [
# src
STLVmFlowVar(name="src",min_value=src['start'],max_value=src['end'],size=4,op="inc"),
- STLVmWriteFlowVar(fv_name="src",pkt_offset= "IP.src"),
+ STLVmWrFlowVar(fv_name="src",pkt_offset= "IP.src"),
# dst
STLVmFlowVar(name="dst",min_value=dst['start'],max_value=dst['end'],size=4,op="inc"),
- STLVmWriteFlowVar(fv_name="dst",pkt_offset= "IP.dst"),
+ STLVmWrFlowVar(fv_name="dst",pkt_offset= "IP.dst"),
# checksum
STLVmFixIpv4(offset = "IP")
diff --git a/scripts/automation/trex_control_plane/stl/examples/stl_run_udp_simple.py b/scripts/automation/trex_control_plane/stl/examples/stl_run_udp_simple.py
index 388e42e7..db005608 100644
--- a/scripts/automation/trex_control_plane/stl/examples/stl_run_udp_simple.py
+++ b/scripts/automation/trex_control_plane/stl/examples/stl_run_udp_simple.py
@@ -47,11 +47,11 @@ def create_pkt (frame_size = 9000, direction=0):
vm = [
# src
STLVmFlowVar(name="src",min_value=src['start'],max_value=src['end'],size=4,op="inc"),
- STLVmWriteFlowVar(fv_name="src",pkt_offset= "IP.src"),
+ STLVmWrFlowVar(fv_name="src",pkt_offset= "IP.src"),
# dst
STLVmFlowVar(name="dst",min_value=dst['start'],max_value=dst['end'],size=4,op="inc"),
- STLVmWriteFlowVar(fv_name="dst",pkt_offset= "IP.dst"),
+ STLVmWrFlowVar(fv_name="dst",pkt_offset= "IP.dst"),
# checksum
STLVmFixIpv4(offset = "IP")
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_hltapi.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_hltapi.py
index 581ea418..593c4c47 100755
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_hltapi.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_hltapi.py
@@ -27,9 +27,9 @@ traffic_config_kwargs = {
'port_handle2': None,
# stream builder parameters
'transmit_mode': 'continuous', # ( continuous | multi_burst | single_burst )
- 'rate_pps': 1, # TODO: support bps and percent once stateless API will, use rate_percent by default
+ 'rate_pps': None,
'rate_bps': None,
- 'rate_percent': 100,
+ 'rate_percent': 10,
'stream_id': None,
'name': None,
'bidirectional': 0,
@@ -663,55 +663,67 @@ class CTRexHltApi(object):
def STLHltStream(**user_kwargs):
kwargs = merge_kwargs(traffic_config_kwargs, user_kwargs)
+ # verify rate is given by at most one arg
+ rate_args = set(['rate_pps', 'rate_bps', 'rate_percent'])
+ intersect_rate_args = list(rate_args & set(user_kwargs.keys()))
+ if len(intersect_rate_args) > 1:
+ raise STLError('More than one rate argument specified: %s' % intersect_rate_args)
+ try:
+ rate_key = intersect_rate_args[0]
+ except IndexError:
+ rate_key = 'rate_percent'
+
if kwargs['length_mode'] == 'imix': # several streams with given length
streams_arr = []
user_kwargs['length_mode'] = 'fixed'
if kwargs['l3_imix1_size'] < 32 or kwargs['l3_imix2_size'] < 32 or kwargs['l3_imix3_size'] < 32 or kwargs['l3_imix4_size'] < 32:
raise STLError('l3_imix*_size should be at least 32')
- total_rate = kwargs['l3_imix1_ratio'] + kwargs['l3_imix2_ratio'] + kwargs['l3_imix3_ratio'] + kwargs['l3_imix4_ratio']
- if total_rate == 0:
+ total_ratio = kwargs['l3_imix1_ratio'] + kwargs['l3_imix2_ratio'] + kwargs['l3_imix3_ratio'] + kwargs['l3_imix4_ratio']
+ if total_ratio == 0:
raise STLError('Used length_mode imix, but all the ratios are 0')
save_to_yaml = kwargs.get('save_to_yaml')
- rate_pps = float(kwargs['rate_pps'])
+ total_rate = float(kwargs[rate_key])
if kwargs['l3_imix1_ratio'] > 0:
if save_to_yaml and type(save_to_yaml) is str:
user_kwargs['save_to_yaml'] = save_to_yaml.replace('.yaml', '_imix1.yaml')
user_kwargs['frame_size'] = kwargs['l3_imix1_size']
- user_kwargs['rate_pps'] = rate_pps * kwargs['l3_imix1_ratio'] / total_rate
+ user_kwargs[rate_key] = total_rate * kwargs['l3_imix1_ratio'] / total_ratio
streams_arr.append(STLHltStream(**user_kwargs))
if kwargs['l3_imix2_ratio'] > 0:
if save_to_yaml and type(save_to_yaml) is str:
user_kwargs['save_to_yaml'] = save_to_yaml.replace('.yaml', '_imix2.yaml')
user_kwargs['frame_size'] = kwargs['l3_imix2_size']
- user_kwargs['rate_pps'] = rate_pps * kwargs['l3_imix2_ratio'] / total_rate
+ user_kwargs[rate_key] = total_rate * kwargs['l3_imix2_ratio'] / total_ratio
streams_arr.append(STLHltStream(**user_kwargs))
if kwargs['l3_imix3_ratio'] > 0:
if save_to_yaml and type(save_to_yaml) is str:
user_kwargs['save_to_yaml'] = save_to_yaml.replace('.yaml', '_imix3.yaml')
user_kwargs['frame_size'] = kwargs['l3_imix3_size']
- user_kwargs['rate_pps'] = rate_pps * kwargs['l3_imix3_ratio'] / total_rate
+ user_kwargs[rate_key] = total_rate * kwargs['l3_imix3_ratio'] / total_ratio
streams_arr.append(STLHltStream(**user_kwargs))
if kwargs['l3_imix4_ratio'] > 0:
if save_to_yaml and type(save_to_yaml) is str:
user_kwargs['save_to_yaml'] = save_to_yaml.replace('.yaml', '_imix4.yaml')
user_kwargs['frame_size'] = kwargs['l3_imix4_size']
- user_kwargs['rate_pps'] = rate_pps * kwargs['l3_imix4_ratio'] / total_rate
+ user_kwargs[rate_key] = total_rate * kwargs['l3_imix4_ratio'] / total_ratio
streams_arr.append(STLHltStream(**user_kwargs))
return streams_arr
# packet generation
packet = generate_packet(**user_kwargs)
try:
+ # TODO: verify if bps is L1 or L2, use L2 for now
+ rate_types_dict = {'rate_pps': 'pps', 'rate_bps': 'bps_L2', 'rate_percent': 'percentage'}
+ rate_stateless = {rate_types_dict[rate_key]: float(kwargs[rate_key])}
transmit_mode = kwargs['transmit_mode']
- rate_pps = kwargs['rate_pps']
pkts_per_burst = kwargs['pkts_per_burst']
if transmit_mode == 'continuous':
- transmit_mode_class = STLTXCont(pps = rate_pps)
+ transmit_mode_class = STLTXCont(**rate_stateless)
elif transmit_mode == 'single_burst':
- transmit_mode_class = STLTXSingleBurst(pps = rate_pps, total_pkts = pkts_per_burst)
+ transmit_mode_class = STLTXSingleBurst(total_pkts = pkts_per_burst, **rate_stateless)
elif transmit_mode == 'multi_burst':
- transmit_mode_class = STLTXMultiBurst(pps = rate_pps, total_pkts = pkts_per_burst,
- count = int(kwargs['burst_loop_count']), ibg = kwargs['inter_burst_gap'])
+ transmit_mode_class = STLTXMultiBurst(total_pkts = pkts_per_burst, count = int(kwargs['burst_loop_count']),
+ ibg = kwargs['inter_burst_gap'], **rate_stateless)
else:
raise STLError('transmit_mode %s not supported/implemented')
except Exception as e:
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py
index 29bad041..4dd07a13 100644
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py
@@ -1,6 +1,9 @@
from collections import namedtuple, OrderedDict
+from trex_stl_packet_builder_scapy import CScapyTRexPktBuilder
+from trex_stl_streams import STLStream
+import base64
import trex_stl_stats
from trex_stl_types import *
import time
@@ -132,10 +135,23 @@ class Port(object):
else:
raise Exception("port {0}: bad state received from server '{1}'".format(self.port_id, port_state))
- # TODO: handle syncing the streams into stream_db
self.next_available_id = long(rc.data()['max_stream_id']) + 1
+ # sync the streams
+ params = {"port_id": self.port_id}
+
+ command = RpcCmdData("get_all_streams", params)
+ rc = self.transmit(command.method, command.params)
+ if rc.bad():
+ return self.err(rc.err())
+
+ for k, v in rc.data()['streams'].iteritems():
+ self.streams[k] = {'next_id': v['next_stream_id'],
+ 'pkt' : base64.b64decode(v['packet']['binary']),
+ 'mode' : v['mode']['type'],
+ 'rate' : STLStream.get_rate_from_field(v['mode']['rate'])}
+
return self.ok()
@@ -161,55 +177,64 @@ class Port(object):
return self.err("Please stop port before attempting to add streams")
# listify
- streams_list = copy.deepcopy(streams_list if isinstance(streams_list, list) else [streams_list])
+ 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()
+ # allocate stream id
+ stream_id = stream.get_id() if stream.get_id() is not None else self.__allocate_stream_id()
+ if stream_id in self.streams:
+ return self.err('Stream ID: {0} already exists'.format(stream_id))
- batch = []
+ # name
+ name = stream.get_name() if stream.get_name() is not None else id(stream)
+ if name in lookup:
+ return self.err("multiple streams with duplicate name: '{0}'".format(name))
+ lookup[name] = stream_id
-
+ batch = []
for stream in streams_list:
+ name = stream.get_name() if stream.get_name() is not None else id(stream)
+ stream_id = lookup[name]
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.set_next_id(next_id)
-
-
stream_json = stream.to_json()
- stream_json['next_stream_id'] = stream.get_next_id()
+ stream_json['next_stream_id'] = next_id
params = {"handler": self.handler,
"port_id": self.port_id,
- "stream_id": stream.get_id(),
+ "stream_id": stream_id,
"stream": stream_json}
cmd = RpcCmdData('add_stream', params)
batch.append(cmd)
- self.streams[stream.get_id()] = stream
rc = self.transmit_batch(batch)
- if not rc:
- return self.err(str(rc))
+ for i, single_rc in enumerate(rc):
+ if single_rc:
+ stream_id = batch[i].params['stream_id']
+ next_id = batch[i].params['stream']['next_stream_id']
+ self.streams[stream_id] = {'next_id' : next_id,
+ 'pkt' : streams_list[i].get_pkt(),
+ 'mode' : streams_list[i].get_mode(),
+ 'rate' : streams_list[i].get_rate()}
- # the only valid state now
- self.state = self.STATE_STREAMS
- return self.ok()
+ self.state = self.STATE_STREAMS if (len(self.streams) > 0) else self.STATE_IDLE
+
+ return self.ok() if rc else self.err(str(rc))
@@ -239,16 +264,16 @@ class Port(object):
cmd = RpcCmdData('remove_stream', params)
batch.append(cmd)
- del self.streams[stream_id]
-
rc = self.transmit_batch(batch)
- if not rc:
- return self.err(rc.err())
+ for i, single_rc in enumerate(rc):
+ if single_rc:
+ id = batch[i].params['stream_id']
+ del self.streams[stream_id]
self.state = self.STATE_STREAMS if (len(self.streams) > 0) else self.STATE_IDLE
- return self.ok()
+ return self.ok() if rc else self.err(rc.err())
# remove all the streams
@@ -273,6 +298,7 @@ class Port(object):
return self.ok()
+
# get a specific stream
def get_stream (self, stream_id):
if stream_id in self.streams:
@@ -283,6 +309,7 @@ class Port(object):
def get_all_streams (self):
return self.streams
+
# start traffic
def start (self, mul, duration, force):
if not self.is_acquired():
@@ -324,7 +351,6 @@ class Port(object):
return self.ok()
-
params = {"handler": self.handler,
"port_id": self.port_id}
@@ -421,6 +447,7 @@ class Port(object):
return self.ok()
+
def get_profile (self):
return self.profile
@@ -496,18 +523,24 @@ class Port(object):
return {}
data = {}
- for id, stream in self.streams.iteritems():
+ for id, obj in self.streams.iteritems():
+
+ # lazy build scapy repr.
+ if not 'pkt_type' in obj:
+ obj['pkt_type'] = CScapyTRexPktBuilder.pkt_layers_desc_from_buffer(obj['pkt'])
+
data[id] = OrderedDict([ ('id', id),
- ('packet_type', stream.get_pkt_type()),
- ('L2 len', stream.get_pkt_len()),
- ('mode' , stream.get_mode()),
- ('rate_pps', stream.get_pps()),
- ('next_stream', stream.get_next_id())
+ ('packet_type', obj['pkt_type']),
+ ('L2 len', len(obj['pkt']) + 4),
+ ('mode', obj['mode']),
+ ('rate', obj['rate']),
+ ('next_stream', obj['next_id'])
])
return {"streams" : OrderedDict(sorted(data.items())) }
+
################# events handler ######################
def async_event_port_stopped (self):
self.state = self.STATE_STREAMS
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_sim.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_sim.py
index 907125e9..54d699d8 100644
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_sim.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_sim.py
@@ -152,19 +152,29 @@ class STLSim(object):
# load streams
cmds_json = []
- id = 1
+ id_counter = 1
lookup = {}
+
# allocate IDs
for stream in stream_list:
- if stream.get_id() == None:
- stream.set_id(id)
- id += 1
+ if stream.get_id() is not None:
+ stream_id = stream.get_id()
+ else:
+ stream_id = id_counter
+ id_counter += 1
- lookup[stream.get_name()] = stream.get_id()
+ name = stream.get_name() if stream.get_name() is not None else id(stream)
+ if name in lookup:
+ raise STLError("multiple streams with name: '{0}'".format(name))
+ lookup[name] = stream_id
# resolve names
for stream in stream_list:
+
+ name = stream.get_name() if stream.get_name() is not None else id(stream)
+ stream_id = lookup[name]
+
next_id = -1
next = stream.get_next()
if next:
@@ -172,19 +182,16 @@ class STLSim(object):
raise STLError("stream dependency error - unable to find '{0}'".format(next))
next_id = lookup[next]
- stream.set_next_id(next_id)
-
- for stream in stream_list:
stream_json = stream.to_json()
- stream_json['next_stream_id'] = stream.get_next_id()
+ stream_json['next_stream_id'] = next_id
cmd = {"id":1,
"jsonrpc": "2.0",
"method": "add_stream",
"params": {"handler": self.handler,
"port_id": self.port_id,
- "stream_id": stream.get_id(),
+ "stream_id": stream_id,
"stream": stream_json}
}
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py
index 34c7a857..ebc686f8 100644
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_stats.py
@@ -224,13 +224,12 @@ class CTRexInfoGenerator(object):
p_type_field_len = 0
for stream_id, stream_id_sum in return_streams_data['streams'].iteritems():
- stream_id_sum['rate_pps'] = format_num(stream_id_sum['rate_pps'], suffix='pps')
stream_id_sum['packet_type'] = self._trim_packet_headers(stream_id_sum['packet_type'], 30)
p_type_field_len = max(p_type_field_len, len(stream_id_sum['packet_type']))
info_table = text_tables.TRexTextTable()
info_table.set_cols_align(["c"] + ["l"] + ["r"] + ["c"] + ["r"] + ["c"])
- info_table.set_cols_width([10] + [p_type_field_len] + [8] + [16] + [10] + [12])
+ info_table.set_cols_width([10] + [p_type_field_len] + [8] + [16] + [15] + [12])
info_table.set_cols_dtype(["t"] + ["t"] + ["t"] + ["t"] + ["t"] + ["t"])
info_table.add_rows([v.values()
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py
index f79d25c3..127d1669 100644
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py
@@ -64,9 +64,9 @@ class STLTXMode(object):
# continuous mode
class STLTXCont(STLTXMode):
- def __init__ (self, pps = None, bps_L1 = None, bps_L2 = None, percentage = None):
+ def __init__ (self, **kwargs):
- super(STLTXCont, self).__init__(pps, bps_L1, bps_L2, percentage)
+ super(STLTXCont, self).__init__(**kwargs)
self.fields['type'] = 'continuous'
@@ -76,12 +76,12 @@ class STLTXCont(STLTXMode):
# single burst mode
class STLTXSingleBurst(STLTXMode):
- def __init__ (self, total_pkts = 1, pps = None, bps_L1 = None, bps_L2 = None, percentage = None):
+ def __init__ (self, total_pkts = 1, **kwargs):
if not isinstance(total_pkts, int):
raise STLArgumentError('total_pkts', total_pkts)
- super(STLTXSingleBurst, self).__init__(pps, bps_L1, bps_L2, percentage)
+ super(STLTXSingleBurst, self).__init__(**kwargs)
self.fields['type'] = 'single_burst'
self.fields['total_pkts'] = total_pkts
@@ -96,10 +96,7 @@ class STLTXMultiBurst(STLTXMode):
pkts_per_burst = 1,
ibg = 0.0, # usec not SEC
count = 1,
- pps = None,
- bps_L1 = None,
- bps_L2 = None,
- percentage = None):
+ **kwargs):
if not isinstance(pkts_per_burst, int):
raise STLArgumentError('pkts_per_burst', pkts_per_burst)
@@ -110,7 +107,7 @@ class STLTXMultiBurst(STLTXMode):
if not isinstance(count, int):
raise STLArgumentError('count', count)
- super(STLTXMultiBurst, self).__init__(pps, bps_L1, bps_L2, percentage)
+ super(STLTXMultiBurst, self).__init__(**kwargs)
self.fields['type'] = 'multi_burst'
self.fields['pkts_per_burst'] = pkts_per_burst
@@ -124,8 +121,24 @@ STLStreamDstMAC_CFG_FILE=0
STLStreamDstMAC_PKT =1
STLStreamDstMAC_ARP =2
+# RX stats class
+class STLRxStats(object):
+ def __init__ (self, user_id):
+ self.fields = {}
+
+ self.fields['enabled'] = True
+ self.fields['stream_id'] = user_id
+ self.fields['seq_enabled'] = False
+ self.fields['latency_enabled'] = False
+ def to_json (self):
+ return dict(self.fields)
+
+ @staticmethod
+ def defaults ():
+ return {'enabled' : False}
+
class STLStream(object):
def __init__ (self,
@@ -158,9 +171,7 @@ class STLStream(object):
self.name = name
self.next = next
- # ID
- self.set_id(stream_id)
- self.set_next_id(None)
+ self.id = stream_id
self.fields = {}
@@ -221,10 +232,9 @@ class STLStream(object):
self.packet_desc = None
if not rx_stats:
- self.fields['rx_stats'] = {}
- self.fields['rx_stats']['enabled'] = False
+ self.fields['rx_stats'] = STLRxStats.defaults()
else:
- self.fields['rx_stats'] = rx_stats
+ self.fields['rx_stats'] = rx_stats.to_json()
def __str__ (self):
@@ -239,14 +249,6 @@ class STLStream(object):
def get_id (self):
return self.id
- def set_id (self, id):
- self.id = id
-
- def get_next_id (self):
- return self.next_id
-
- def set_next_id (self, next_id):
- self.next_id = next_id
def get_name (self):
return self.name
@@ -254,26 +256,44 @@ class STLStream(object):
def get_next (self):
return self.next
- def get_pkt_type (self):
- if self.packet_desc == None:
- self.packet_desc = CScapyTRexPktBuilder.pkt_layers_desc_from_buffer(self.get_pkt())
-
- return self.packet_desc
def get_pkt (self):
return self.pkt
def get_pkt_len (self, count_crc = True):
- pkt_len = len(base64.b64decode(self.get_pkt()))
+ pkt_len = len(self.get_pkt())
if count_crc:
pkt_len += 4
return pkt_len
+ def get_pkt_type (self):
+ if self.packet_desc == None:
+ self.packet_desc = CScapyTRexPktBuilder.pkt_layers_desc_from_buffer(self.get_pkt())
+
+ return self.packet_desc
+
def get_mode (self):
return self.mode_desc
+ @staticmethod
+ def get_rate_from_field (rate_json):
+ t = rate_json['type']
+ v = rate_json['value']
+
+ if t == "pps":
+ return format_num(v, suffix = "pps")
+ elif t == "bps_L1":
+ return format_num(v, suffix = "bps (L1)")
+ elif t == "bps_L2":
+ return format_num(v, suffix = "bps (L2)")
+ elif t == "percentage":
+ return format_num(v, suffix = "%")
+
+ def get_rate (self):
+ return self.get_rate_from_field(self.fields['mode']['rate'])
+
def to_yaml (self):
y = {}
@@ -338,6 +358,8 @@ class YAMLLoader(object):
def __parse_mode (self, mode_obj):
+ if not mode_obj:
+ return None
rate_parser = set(mode_obj).intersection(['pps', 'bps_L1', 'bps_L2', 'percentage'])
if len(rate_parser) != 1:
@@ -371,6 +393,18 @@ class YAMLLoader(object):
+ def __parse_rx_stats (self, rx_stats_obj):
+
+ # no such object
+ if not rx_stats_obj or rx_stats_obj.get('enabled') == False:
+ return None
+
+ user_id = rx_stats_obj.get('stream_id')
+ if user_id == None:
+ raise STLError("enabled RX stats section must contain 'stream_id' field")
+
+ return STLRxStats(user_id = user_id)
+
def __parse_stream (self, yaml_object):
s_obj = yaml_object['stream']
@@ -384,23 +418,21 @@ class YAMLLoader(object):
# mode
- mode_obj = s_obj.get('mode')
- if not mode_obj:
- raise STLError("YAML file must contain 'mode' field")
-
- mode = self.__parse_mode(mode_obj)
+ mode = self.__parse_mode(s_obj.get('mode'))
+ # rx stats
+ rx_stats = self.__parse_rx_stats(s_obj.get('rx_stats'))
- defaults = STLStream()
+ defaults = STLStream()
# create the stream
stream = STLStream(name = yaml_object.get('name'),
packet = builder,
mode = mode,
+ rx_stats = rx_stats,
enabled = s_obj.get('enabled', defaults.fields['enabled']),
self_start = s_obj.get('self_start', defaults.fields['self_start']),
isg = s_obj.get('isg', defaults.fields['isg']),
- rx_stats = s_obj.get('rx_stats', defaults.fields['rx_stats']),
next = yaml_object.get('next'),
action_count = s_obj.get('action_count', defaults.fields['action_count']),
mac_src_override_by_pkt = s_obj.get('mac_src_override_by_pkt', 0),
@@ -523,7 +555,7 @@ class STLProfile(object):
streams.append(STLStream(name = i,
packet = CScapyTRexPktBuilder(pkt_buffer = cap, vm = vm),
- mode = STLTXSingleBurst(total_pkts = 1),
+ mode = STLTXSingleBurst(total_pkts = 1, percentage = 100),
self_start = True if (i == 1) else False,
isg = (ts_usec - last_ts_usec), # seconds to usec
action_count = action_count,
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_types.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_types.py
index d4ad8bd2..496bea13 100644
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_types.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_types.py
@@ -54,6 +54,10 @@ class RC():
s += format_text("\n{0}".format(x.data), 'bold')
return s
+ def __iter__(self):
+ return self.rc_list.__iter__()
+
+
def prn_func (self, msg, newline = True):
if newline:
print msg