summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHanoh Haim <hhaim@cisco.com>2016-03-10 19:23:30 +0200
committerHanoh Haim <hhaim@cisco.com>2016-03-10 19:23:30 +0200
commit2be2f7e96be26fbe6dd6763f2ec97fb248abb330 (patch)
treebb11e3cb8ef8807799168156aa1ba6235839e76c
parent54fb838e24607af8532f725997b670f482abfe96 (diff)
basic doc for python client API
-rw-r--r--.gitignore2
-rwxr-xr-xscripts/automation/trex_control_plane/doc/conf.py8
-rw-r--r--scripts/automation/trex_control_plane/doc_stl/conf.py4
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py65
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py234
5 files changed, 302 insertions, 11 deletions
diff --git a/.gitignore b/.gitignore
index aa35301e..39995917 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,6 +24,8 @@ scripts/bp-sim-*
scripts/doc/*
scripts/mock-*
scripts/automation/trex_control_plane/doc/_build/*
+scripts/automation/trex_control_plane/doc_stl/_build/*
+scripts/a.pcap
scripts/exp/http1_with_option_ipv6.pcap
scripts/exp/http1_with_option.pcap
diff --git a/scripts/automation/trex_control_plane/doc/conf.py b/scripts/automation/trex_control_plane/doc/conf.py
index aeee475f..9d32ca24 100755
--- a/scripts/automation/trex_control_plane/doc/conf.py
+++ b/scripts/automation/trex_control_plane/doc/conf.py
@@ -123,10 +123,12 @@ todo_include_todos = True
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
-html_theme = 'sphinx_rtd_theme'
-html_theme_options = {
+#html_theme = 'sphinx_rtd_theme'
+html_theme = 'classic'
+
+#html_theme_options = {
# "rightsidebar": "true"
- }
+ # }
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
diff --git a/scripts/automation/trex_control_plane/doc_stl/conf.py b/scripts/automation/trex_control_plane/doc_stl/conf.py
index 6dfb4f70..fe6b27bc 100644
--- a/scripts/automation/trex_control_plane/doc_stl/conf.py
+++ b/scripts/automation/trex_control_plane/doc_stl/conf.py
@@ -121,8 +121,8 @@ todo_include_todos = True
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#html_theme = 'sphinx_rtd_theme'
-#html_theme = 'classic'
-html_theme = 'sphinxdoc'
+html_theme = 'classic'
+#html_theme = 'sphinxdoc'
#html_theme_options = {
# "rightsidebar": "true"
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py
index 6a2e268f..59a047ec 100644
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py
@@ -527,7 +527,14 @@ def check_for_int (val):
class CTRexVmDescFlowVar(CTRexVmDescBase):
+ """
+ flow var instruction
+ """
+
def __init__(self, name, init_value=None, min_value=0, max_value=255, size=4, step=1,op="inc"):
+ """
+
+ """
super(CTRexVmDescFlowVar, self).__init__()
self.name = name;
assert type(name)==str, 'type of name is not str'
@@ -666,20 +673,66 @@ class CTRexVmDescTupleGen(CTRexVmDescBase):
################################################################################################
class CScapyTRexPktBuilder(CTrexPktBuilderInterface):
-
"""
- This class defines the TRex API of building a packet using scapy package.
- Using this class the user can also define how TRex will handle the packet by specifying the VM setting.
+ This class defines the TRex API of building a packet and Field engine using scapy package.
+ Using this class the user can also define how TRex will handle the packet by specifying the Field engine setting.
pkt could be Scapy pkt or pcap file name
-
- When path_relative_to_profile is True load pcap file from path relative to the profile
+ When path_relative_to_profile is a True load pcap file from a path relative to the profile
"""
+
def __init__(self, pkt = None, pkt_buffer = None, vm = None, path_relative_to_profile = False, build_raw = True, remove_fcs = True):
"""
Instantiate a CTRexPktBuilder object
:parameters:
- None
+
+ pkt : Scapy or pcap file filename
+ a scapy packet
+
+ pkt_buffer : string
+ a packet as buffer
+
+ vm : list
+ a list of instructions to manipolate packet fields
+
+ path_relative_to_profile : bool
+ in case pkt is pcap file, do we want to load it relative to profile file
+
+ build_raw : bool
+ Do we want to build scapy in case buffer was given. good for cases we want offset to be taken from scapy
+
+ remove_fcs : bool
+ in case of buffer do we want to remove fcs
+
+ for Example::
+
+ # packet is scapy
+ STLPktBuilder( pkt = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/UDP(dport=12,sport=1025)/(10*'x')
+
+ # packet is taken from pcap file relative to python
+ STLPktBuilder(pkt ="stl/yaml/udp_64B_no_crc.pcap")
+
+ # packet is taken from pcap file relative to profile file
+ STLPktBuilder(pkt ="stl/yaml/udp_64B_no_crc.pcap",
+ path_relative_to_profile = True)
+
+
+ vm = CTRexScRaw( [ STLVmTupleGen ( ip_min="16.0.0.1", ip_max="16.0.0.2",
+ port_min=1025, port_max=65535,
+ name="tuple"), # define tuple gen
+
+ STLVmWrFlowVar (fv_name="tuple.ip", pkt_offset= "IP.src" ), # write ip to packet IP.src
+ STLVmFixIpv4(offset = "IP"), # fix checksum
+ STLVmWrFlowVar (fv_name="tuple.port", pkt_offset= "UDP.sport" ) #write udp.port
+ ]
+ );
+
+ base_pkt = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/UDP(dport=12,sport=1025)
+ pad = max(0, size - len(base_pkt)) * 'x'
+
+ STLPktBuilder(pkt = base_pkt/pad,
+ vm= vm)
+
"""
super(CScapyTRexPktBuilder, self).__init__()
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 7fc132b1..b7368767 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
@@ -17,7 +17,35 @@ import copy
# base class for TX mode
class STLTXMode(object):
+ """ mode rate speed """
+
def __init__ (self, pps = None, bps_L1 = None, bps_L2 = None, percentage = None):
+ """
+ Speed could be in packet per second (pps) or L2/L1 bps or port precent
+ only one of them is valid.
+ you can enter pps =10000 oe bps_L1=10
+
+ :parameters:
+ pps : float
+ packet per second
+
+ bps_L1 : float
+ bit per second L1 (with IPG)
+
+ bps_L2 : float
+ bit per second L2 (Ethernet-FCS)
+
+ percentage : float
+ link interface precent 0-100 e.g. 10 is 10%% of the port link setup
+
+ For example::
+ mode = STLTXCont(pps = 10)
+ mode = STLTXCont(bps_L1 = 10000000) #10mbps L1
+ mode = STLTXCont(bps_L2 = 10000000) #10mbps L2
+ mode = STLTXCont(percentage = 10) #10%
+
+ """
+
args = [pps, bps_L1, bps_L2, percentage]
# default
@@ -62,11 +90,21 @@ class STLTXMode(object):
# continuous mode
class STLTXCont(STLTXMode):
+ """ continuous mode """
def __init__ (self, **kwargs):
+ """
+ continuous mode
+
+ see :class:`trex_stl_lib.trex_stl_streams.STLTXMode` for rate
+ For example::
+ mode = STLTXCont(pps = 10)
+
+ """
super(STLTXCont, self).__init__(**kwargs)
+
self.fields['type'] = 'continuous'
@staticmethod
@@ -75,8 +113,23 @@ class STLTXCont(STLTXMode):
# single burst mode
class STLTXSingleBurst(STLTXMode):
+ """ Single burst mode """
def __init__ (self, total_pkts = 1, **kwargs):
+ """
+ single burst mode
+
+ :parameters:
+ total_pkts : int
+ how many packets for this burst
+
+ see :class:`trex_stl_lib.trex_stl_streams.STLTXMode` for rate
+
+ For example::
+ mode = STLTXSingleBurst( pps = 10, total_pkts = 1)
+
+ """
+
if not isinstance(total_pkts, int):
raise STLArgumentError('total_pkts', total_pkts)
@@ -92,12 +145,34 @@ class STLTXSingleBurst(STLTXMode):
# multi burst mode
class STLTXMultiBurst(STLTXMode):
+ """ Multi burst mode """
def __init__ (self,
pkts_per_burst = 1,
ibg = 0.0, # usec not SEC
count = 1,
**kwargs):
+ """
+ Multi burst mode
+
+ :parameters:
+
+ pkts_per_burst: int
+ how many packets per burst
+
+ ibg : float
+ inter burst gap in usec 1000,000.0 is 1 sec
+
+ count : int
+ how many bursts
+
+ see :class:`trex_stl_lib.trex_stl_streams.STLTXMode` for rate
+
+ For example::
+ mode = STLTXMultiBurst(pps = 10, pkts_per_burst = 1,count 10, ibg=10.0)
+
+ """
+
if not isinstance(pkts_per_burst, int):
raise STLArgumentError('pkts_per_burst', pkts_per_burst)
@@ -142,6 +217,19 @@ class STLFlowStats(object):
return {'enabled' : False}
class STLStream(object):
+ """ One stream object, include mode, Field Engine mode packet template and Rx stats
+
+ For example::
+ base_pkt = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/UDP(dport=12,sport=1025)
+ pad = max(0, size - len(base_pkt)) * 'x'
+
+ STLStream( isg = 10.0, # star in delay
+ name ='S0',
+ packet = STLPktBuilder(pkt = base_pkt/pad),
+ mode = STLTXSingleBurst( pps = 10, total_pkts = 1),
+ next = 'S1'), # point to next stream
+
+ """
def __init__ (self,
name = None,
@@ -158,6 +246,58 @@ class STLStream(object):
mac_src_override_by_pkt=None,
mac_dst_override_mode=None #see STLStreamDstMAC_xx
):
+ """
+ Stream object
+
+ :parameters:
+
+ name : string
+ The name of the stream. Needed if this stream is dependent on another stream and another stream need to refer to this stream by its name.
+
+ packet : STLPktBuilder
+ The template packet and field engine program e.g. packet = STLPktBuilder(pkt = base_pkt/pad)
+
+ mode : STLTXCont or STLTXSingleBurst or STLTXMultiBurst
+
+ enabled : bool
+ if the stream is enabled.
+
+ self_start : bool
+ In case it is False another stream will activate it
+
+ isg : float
+ Inter stream gap in usec. time to wait until stream will send the first packet
+
+ flow_stats : STLFlowStats
+ Per stream statistic object see STLFlowStats
+
+ next : string
+ The name of the stream to activate
+
+ stream_id :
+ for HLTAPI usage
+
+ action_count : uint16_t
+ In case there is a next stream how many loops until stopping. Default is zero, which mean unlimited
+
+ random_seed: uint16_t
+ If given the seed for this stream will be this value. Good in case you need a deterministic random value
+
+ mac_src_override_by_pkt : bool
+ Template packet will set src MAC
+
+ mac_dst_override_mode=None : STLStreamDstMAC_xx
+ Template packet will set dst MAC
+
+
+ :return:
+ None
+
+ :raises:
+ None
+
+ """
+
# type checking
validate_type('mode', mode, STLTXMode)
@@ -254,23 +394,31 @@ class STLStream(object):
return s
def to_json (self):
+ """
+ return json format
+ """
return dict(self.fields)
def get_id (self):
+ """ Get the stream id after resolution """
return self.id
def get_name (self):
+ """ Get the stream name """
return self.name
def get_next (self):
+ """ Get next stream object """
return self.next
def get_pkt (self):
+ """ Get packet as string """
return self.pkt
def get_pkt_len (self, count_crc = True):
+ """ Get packet number of bytes """
pkt_len = len(self.get_pkt())
if count_crc:
pkt_len += 4
@@ -279,6 +427,7 @@ class STLStream(object):
def get_pkt_type (self):
+ """ Get packet description for example IP:UDP """
if self.packet_desc == None:
self.packet_desc = CScapyTRexPktBuilder.pkt_layers_desc_from_buffer(self.get_pkt())
@@ -289,6 +438,7 @@ class STLStream(object):
@staticmethod
def get_rate_from_field (rate_json):
+ """ Get rate from json """
t = rate_json['type']
v = rate_json['value']
@@ -305,6 +455,7 @@ class STLStream(object):
return self.get_rate_from_field(self.fields['mode']['rate'])
def to_pkt_dump (self):
+ """ print packet description from scapy """
if self.name:
print "Stream Name: ",self.name
scapy_b = self.scapy_pkt_builder;
@@ -316,6 +467,7 @@ class STLStream(object):
def to_yaml (self):
+ """ convert to YAML """
y = {}
if self.name:
@@ -337,6 +489,7 @@ class STLStream(object):
# returns the Python code (text) to build this stream, inside the code it will be in variable "stream"
def to_code (self):
+ """ convert to Python code as profile """
packet = Ether(self.pkt)
packet.hide_defaults()
payload = packet.getlayer('Raw')
@@ -436,6 +589,7 @@ class STLStream(object):
return r'\x{0:02x}'.format(ord(match.group()))
def dump_to_yaml (self, yaml_file = None):
+ """ print as yaml """
yaml_dump = yaml.dump([self.to_yaml()], default_flow_style = False)
# write to file if provided
@@ -583,7 +737,45 @@ class YAMLLoader(object):
# profile class
class STLProfile(object):
+ """ Describe a list of streams
+
+ For example::
+
+ profile = STLProfile( [ STLStream( isg = 10.0, # star in delay
+ name ='S0',
+ packet = STLPktBuilder(pkt = base_pkt/pad),
+ mode = STLTXSingleBurst( pps = 10, total_pkts = self.burst_size),
+ next = 'S1'), # point to next stream
+
+ STLStream( self_start = False, # stream is disabled enable trow S0
+ name ='S1',
+ packet = STLPktBuilder(pkt = base_pkt1/pad),
+ mode = STLTXSingleBurst( pps = 10, total_pkts = self.burst_size),
+ next = 'S2' ),
+
+ STLStream( self_start = False, # stream is disabled enable trow S0
+ name ='S2',
+ packet = STLPktBuilder(pkt = base_pkt2/pad),
+ mode = STLTXSingleBurst( pps = 10, total_pkts = self.burst_size )
+ )
+ ]).get_streams()
+
+
+
+ """
+
def __init__ (self, streams = None):
+ """
+
+ :parameters:
+
+ streams : list of STLStream
+ a list of stream objects
+
+
+ """
+
+
if streams == None:
streams = []
@@ -597,6 +789,7 @@ class STLProfile(object):
def get_streams (self):
+ """ Get the list of stream"""
return self.streams
def __str__ (self):
@@ -605,6 +798,8 @@ class STLProfile(object):
@staticmethod
def load_yaml (yaml_file):
+ """ load from YAML file a profile with number of streams"""
+
# check filename
if not os.path.isfile(yaml_file):
raise STLError("file '{0}' does not exists".format(yaml_file))
@@ -617,6 +812,8 @@ class STLProfile(object):
@staticmethod
def load_py (python_file):
+ """ load from Python profile """
+
# check filename
if not os.path.isfile(python_file):
raise STLError("file '{0}' does not exists".format(python_file))
@@ -648,6 +845,30 @@ class STLProfile(object):
# loop_count = 0 means loop forever
@staticmethod
def load_pcap (pcap_file, ipg_usec = None, speedup = 1.0, loop_count = 1, vm = None):
+ """ Convert a pcap file with a number of packets to a list of connected streams
+
+ packet1->packet2->packet3 etc
+
+ :parameters:
+
+ pcap_file : string
+ The name of the pcap file
+
+ ipg_usec : float
+ The inter packet gap in usec. in case of None IPG is taken from pcap file
+
+ speedup : float
+ By which factor to get IPG smaller so we will send pcap file in speedup
+
+ loop_count : uint16_t
+ how many loops to repeat the pcap file
+
+ vm : list
+ A list of Field engine instructions
+
+ :return: STLProfile
+
+ """
# check filename
if not os.path.isfile(pcap_file):
@@ -696,6 +917,16 @@ class STLProfile(object):
@staticmethod
def load (filename):
+ """ load a profile by its type supported type are
+ * py
+ * yaml
+ * pcap file that converted to profile automaticly
+
+ :parameters:
+ filename : string as filename
+
+ """
+
x = os.path.basename(filename).split('.')
suffix = x[1] if (len(x) == 2) else None
@@ -714,6 +945,7 @@ class STLProfile(object):
return profile
def dump_as_pkt (self):
+ """ dump the profile as scapy packet. in case it is raw convert to scapy and dump it"""
cnt=0;
for stream in self.streams:
print "======================="
@@ -723,6 +955,7 @@ class STLProfile(object):
stream.to_pkt_dump()
def dump_to_yaml (self, yaml_file = None):
+ """ convert it to yaml """
yaml_list = [stream.to_yaml() for stream in self.streams]
yaml_str = yaml.dump(yaml_list, default_flow_style = False)
@@ -734,6 +967,7 @@ class STLProfile(object):
return yaml_str
def dump_to_code (self, profile_file = None):
+ """ convert it to Python native profile. yeah this is cool """
profile_dump = '''# !!! Auto-generated code !!!
from trex_stl_lib.api import *