diff options
-rw-r--r-- | scripts/api/stl/examples/stl_simple_burst.py | 13 | ||||
-rw-r--r-- | scripts/automation/trex_control_plane/stl/rpc_defaults.yaml | 124 | ||||
-rw-r--r-- | scripts/automation/trex_control_plane/stl/trex_stl_port.py | 37 | ||||
-rw-r--r-- | scripts/automation/trex_control_plane/stl/trex_stl_streams.py | 46 | ||||
-rw-r--r-- | src/rpc-server/commands/trex_rpc_cmd_general.cpp | 6 | ||||
-rw-r--r-- | src/stateless/cp/trex_stateless_port.cpp | 5 | ||||
-rw-r--r-- | src/stateless/cp/trex_stateless_port.h | 6 | ||||
-rw-r--r-- | src/stateless/cp/trex_stream.cpp | 11 | ||||
-rw-r--r-- | src/stateless/cp/trex_stream.h | 8 |
9 files changed, 115 insertions, 141 deletions
diff --git a/scripts/api/stl/examples/stl_simple_burst.py b/scripts/api/stl/examples/stl_simple_burst.py index 91fc9e5e..1e3e7695 100644 --- a/scripts/api/stl/examples/stl_simple_burst.py +++ b/scripts/api/stl/examples/stl_simple_burst.py @@ -14,12 +14,15 @@ def simple_burst (): pkt = STLPktBuilder(pkt = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/UDP(dport=12,sport=1025)/IP()/'a_payload_example') # create two bursts and link them - s1 = STLStream(packet = pkt, - mode = STLTXSingleBurst(total_pkts = 5000)) + s1 = STLStream(name = 'A', + packet = pkt, + mode = STLTXSingleBurst(total_pkts = 5000), + next = 'B') - s2 = STLStream(packet = pkt, - mode = STLTXSingleBurst(total_pkts = 3000), - next_stream_id = s1.get_id()) + s2 = STLStream(name = 'B', + self_start = False, + packet = pkt, + mode = STLTXSingleBurst(total_pkts = 3000)) # connect to server c.connect() 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 diff --git a/src/rpc-server/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/commands/trex_rpc_cmd_general.cpp index 084e154a..6ac88352 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_general.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_general.cpp @@ -310,9 +310,9 @@ TrexRpcCmdGetPortStatus::_run(const Json::Value ¶ms, Json::Value &result) { TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id); - result["result"]["owner"] = (port->get_owner().is_free() ? "" : port->get_owner().get_name()); - result["result"]["state"] = port->get_state_as_string(); - + result["result"]["owner"] = (port->get_owner().is_free() ? "" : port->get_owner().get_name()); + result["result"]["state"] = port->get_state_as_string(); + result["result"]["max_stream_id"] = port->get_max_stream_id(); return (TREX_RPC_CMD_OK); } diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index a281e428..8ee46d29 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -343,6 +343,11 @@ TrexStatelessPort::get_state_as_string() const { return "UNKNOWN"; } +int +TrexStatelessPort::get_max_stream_id() const { + return m_stream_table.get_max_stream_id(); +} + void TrexStatelessPort::get_properties(std::string &driver, TrexPlatformApi::driver_speed_e &speed) { diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index 64cf73a4..b0b0ddf3 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -203,6 +203,12 @@ public: std::string get_state_as_string() const; /** + * the the max stream id currently assigned + * + */ + int get_max_stream_id() const; + + /** * fill up properties of the port * * @author imarom (16-Sep-15) diff --git a/src/stateless/cp/trex_stream.cpp b/src/stateless/cp/trex_stream.cpp index 077c30b4..256f7de8 100644 --- a/src/stateless/cp/trex_stream.cpp +++ b/src/stateless/cp/trex_stream.cpp @@ -201,6 +201,17 @@ TrexStream * TrexStreamTable::get_stream_by_id(uint32_t stream_id) { } } +int +TrexStreamTable::get_max_stream_id() const { + int max_id = 0; + + for (const auto stream : m_stream_table) { + max_id = std::max(stream.first, max_id); + } + + return max_id; +} + void TrexStreamTable::get_id_list(std::vector<uint32_t> &id_list) { id_list.clear(); diff --git a/src/stateless/cp/trex_stream.h b/src/stateless/cp/trex_stream.h index 525bf594..72e7bb8b 100644 --- a/src/stateless/cp/trex_stream.h +++ b/src/stateless/cp/trex_stream.h @@ -363,6 +363,14 @@ public: TrexStream * get_stream_by_id(uint32_t stream_id); /** + * get max stream ID assigned + * + * + * @return int + */ + int get_max_stream_id() const; + + /** * populate a list with all the stream IDs * * @author imarom (06-Sep-15) |