summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorimarom <imarom@cisco.com>2016-02-17 09:58:32 -0500
committerimarom <imarom@cisco.com>2016-02-17 09:58:32 -0500
commita5788f0e036baa9c28eab4abb705affc89abc498 (patch)
treeaaad88256c8b8268aa8e4bab3f558d71af275655
parentd9b8bb0ba62d750ab13a1cda5f33bbfcb1f30358 (diff)
stl_pcap.py example - how to transmit a pcap
-rw-r--r--scripts/automation/trex_control_plane/stl/examples/stl_pcap.py99
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py3
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py56
-rw-r--r--scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py23
-rwxr-xr-xscripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py7
5 files changed, 165 insertions, 23 deletions
diff --git a/scripts/automation/trex_control_plane/stl/examples/stl_pcap.py b/scripts/automation/trex_control_plane/stl/examples/stl_pcap.py
new file mode 100644
index 00000000..a729a572
--- /dev/null
+++ b/scripts/automation/trex_control_plane/stl/examples/stl_pcap.py
@@ -0,0 +1,99 @@
+import stl_path
+from trex_stl_lib.api import *
+import argparse
+
+
+def create_vm (ip_start, ip_end):
+ vm =[
+
+ # dest
+ STLVmFlowVar(name="dst", min_value = ip_start, max_value = ip_end, size = 4, op = "inc"),
+ STLVmWrFlowVar(fv_name="dst",pkt_offset= "IP.dst"),
+
+ # checksum
+ STLVmFixIpv4(offset = "IP")
+
+ ]
+
+ return vm
+
+
+def inject_pcap (pcap_file, port, loop_count, ipg_usec, use_vm):
+
+ # create client
+ c = STLClient()
+
+ try:
+ if use_vm:
+ vm = create_vm("10.0.0.1", "10.0.0.254")
+ else:
+ vm = None
+
+ profile = STLProfile.load_pcap(pcap_file, ipg_usec = ipg_usec, loop_count = loop_count, vm = vm)
+
+ print "Loaded pcap {0} with {1} packets...\n".format(pcap_file, len(profile))
+
+ # uncomment this for simulator run
+ #STLSim().run(profile.get_streams(), outfile = 'out.cap')
+
+ c.connect()
+ c.reset(ports = [port])
+ stream_ids = c.add_streams(profile.get_streams(), ports = [port])
+
+ c.clear_stats()
+
+ c.start()
+ c.wait_on_traffic(ports = [port])
+
+ stats = c.get_stats()
+ opackets = stats[port]['opackets']
+ print "{0} packets were Tx on port {1}\n".format(opackets, port)
+
+ except STLError as e:
+ print e
+
+ finally:
+ c.disconnect()
+
+
+def setParserOptions():
+ parser = argparse.ArgumentParser(prog="stl_pcap.py")
+
+ parser.add_argument("-f", help = "pcap file to inject",
+ dest = "pcap",
+ required = True,
+ type = str)
+
+ parser.add_argument("-p", help = "port to inject on",
+ dest = "port",
+ required = True,
+ type = int)
+
+ parser.add_argument("-n", help = "How many times to inject pcap [default is 1, 0 means forever]",
+ dest = "loop_count",
+ default = 1,
+ type = int)
+
+ parser.add_argument("-i", help = "IPG in usec",
+ dest = "ipg",
+ default = 10.0,
+ type = float)
+
+
+ parser.add_argument("-x", help = "Iterate over IP dest",
+ dest = "use_vm",
+ default = False,
+ action = "store_true")
+
+ return parser
+
+def main ():
+ parser = setParserOptions()
+ options = parser.parse_args()
+
+ inject_pcap(options.pcap, options.port, options.loop_count, options.ipg, options.use_vm)
+
+# inject pcap
+if __name__ == '__main__':
+ main()
+
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py
index 46d33e3e..fe162096 100644
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py
@@ -1984,6 +1984,7 @@ class STLClient(object):
self.push_line.__doc__,
parsing_opts.FILE_PATH,
parsing_opts.PORT_LIST_WITH_ALL,
+ parsing_opts.COUNT,
parsing_opts.DURATION,
parsing_opts.IPG,
parsing_opts.SPEEDUP,
@@ -2010,7 +2011,7 @@ class STLClient(object):
profile = STLProfile.load_pcap(opts.file[0],
opts.ipg_usec,
opts.speedup,
- loop = True if opts.duration != -1 else False)
+ opts.count)
id_list = self.add_streams(profile.get_streams(), opts.ports)
self.start(ports = opts.ports, duration = opts.duration, force = opts.force)
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 c788e277..e028d6d5 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
@@ -627,8 +627,7 @@ class CScapyTRexPktBuilder(CTrexPktBuilderInterface):
self.vm_low_level = None
self.metadata=""
self.path_relative_to_profile = path_relative_to_profile
-
- was_set=False
+
if pkt != None and pkt_buffer != None:
raise CTRexPacketBuildException(-15, "packet builder cannot be provided with both pkt and pkt_buffer")
@@ -636,9 +635,8 @@ class CScapyTRexPktBuilder(CTrexPktBuilderInterface):
# process packet
if pkt != None:
self.set_packet(pkt)
- was_set=True
- if pkt_buffer != None:
+ elif pkt_buffer != None:
self.set_pkt_as_str(pkt_buffer)
# process VM
@@ -647,10 +645,10 @@ class CScapyTRexPktBuilder(CTrexPktBuilderInterface):
raise CTRexPacketBuildException(-14, "bad value for variable vm")
self.add_command(vm if isinstance(vm, CTRexScRaw) else CTRexScRaw(vm))
- was_set=True
- if was_set:
- self.compile ()
+ # if we have packet and VM - compile now
+ if (self.pkt or self.pkt_raw) and (self.vm_scripts):
+ self.compile()
def dump_vm_data_as_yaml(self):
@@ -782,21 +780,20 @@ class CScapyTRexPktBuilder(CTrexPktBuilderInterface):
return True
def compile (self):
- self.vm_low_level=CTRexVmEngine()
if self.pkt == None and self.pkt_raw == None:
raise CTRexPacketBuildException(-14, "Packet is empty")
- if self.pkt:
- self.pkt.build();
+ self.vm_low_level = CTRexVmEngine()
+
+ # before VM compile set this to false
+ self.is_pkt_built = False
+
+ # compile the VM
for sc in self.vm_scripts:
if isinstance(sc, CTRexScRaw):
self._compile_raw(sc)
- #for obj in self.vm_scripts:
- # # tuple gen script
- # if isinstance(obj, CTRexScIpv4TupleGen)
- # self._add_tuple_gen(tuple_gen)
####################################################
# private
@@ -858,13 +855,40 @@ class CScapyTRexPktBuilder(CTrexPktBuilderInterface):
self.vm_low_level.split_by_var = obj.split_by_field
+ # lazy packet build only on demand
+ def __lazy_build_packet (self):
+ # alrady built ? bail out
+ if self.is_pkt_built:
+ return
+
+ # for buffer, promote to a scapy packet
+ if self.pkt_raw:
+ self.pkt = Ether(self.pkt_raw)
+ self.pkt.build()
+ self.pkt_raw = None
+
+ # regular scapy packet
+ elif self.pkt:
+ self.pkt.build()
+
+ else:
+ # should not reach here
+ raise CTRexPacketBuildException(-11, 'empty packet')
+
+
+ self.is_pkt_built = True
+
def _pkt_layer_offset (self,layer_name):
- assert self.pkt != None, 'empty packet'
+
+ self.__lazy_build_packet()
+
p_utl=CTRexScapyPktUtl(self.pkt);
return p_utl.get_layer_offet_by_str(layer_name)
def _name_to_offset(self,field_name):
- assert self.pkt != None, 'empty packet'
+
+ self.__lazy_build_packet()
+
p_utl=CTRexScapyPktUtl(self.pkt);
return p_utl.get_field_offet_by_str(field_name)
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 130beabe..b72b5d35 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
@@ -2,7 +2,7 @@
from trex_stl_exceptions import *
from trex_stl_packet_builder_interface import CTrexPktBuilderInterface
-from trex_stl_packet_builder_scapy import CScapyTRexPktBuilder, Ether, IP, RawPcapReader
+from trex_stl_packet_builder_scapy import CScapyTRexPktBuilder, Ether, IP, UDP, TCP, RawPcapReader
from collections import OrderedDict, namedtuple
from dpkt import pcap
@@ -194,6 +194,7 @@ class STLStream(object):
self.fields['packet'] = packet.dump_pkt()
self.fields['vm'] = packet.get_vm_data()
+ self.pkt = base64.b64decode(self.fields['packet']['binary'])
# this is heavy, calculate lazy
self.packet_desc = None
@@ -234,12 +235,15 @@ class STLStream(object):
def get_pkt_type (self):
if self.packet_desc == None:
- self.packet_desc = CScapyTRexPktBuilder.pkt_layers_desc_from_buffer(base64.b64decode(self.fields['packet']['binary']))
+ 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.fields['packet']['binary']))
+ pkt_len = len(base64.b64decode(self.get_pkt()))
if count_crc:
pkt_len += 4
@@ -454,8 +458,10 @@ class STLProfile(object):
finally:
sys.path.remove(basedir)
+
+ # loop_count = 0 means loop forever
@staticmethod
- def load_pcap (pcap_file, ipg_usec = None, speedup = 1.0, loop = False):
+ def load_pcap (pcap_file, ipg_usec = None, speedup = 1.0, loop_count = 1, vm = None):
# check filename
if not os.path.isfile(pcap_file):
raise STLError("file '{0}' does not exists".format(pcap_file))
@@ -474,16 +480,19 @@ class STLProfile(object):
# handle last packet
if i == len(pkts):
- next = 1 if loop else None
+ next = 1
+ action_count = loop_count
else:
next = i + 1
+ action_count = 0
streams.append(STLStream(name = i,
- packet = CScapyTRexPktBuilder(pkt_buffer = cap),
+ packet = CScapyTRexPktBuilder(pkt_buffer = cap, vm = vm),
mode = STLTXSingleBurst(total_pkts = 1),
self_start = True if (i == 1) else False,
isg = (ts_usec - last_ts_usec), # seconds to usec
+ action_count = action_count,
next = next))
last_ts_usec = ts_usec
@@ -525,3 +534,5 @@ class STLProfile(object):
return yaml_str
+ def __len__ (self):
+ return len(self.streams)
diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py
index 84dd5090..92e9a1d6 100755
--- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py
+++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py
@@ -26,6 +26,7 @@ TOTAL = 14
FULL_OUTPUT = 15
IPG = 16
SPEEDUP = 17
+COUNT = 18
GLOBAL_STATS = 50
PORT_STATS = 51
@@ -216,6 +217,12 @@ OPTIONS_DB = {MULTIPLIER: ArgumentPack(['-m', '--multiplier'],
'default': 1.0,
'type': float}),
+ COUNT: ArgumentPack(['-n', '--count'],
+ {'help': "How many times to perform action [default is 1, 0 means forever]",
+ 'dest': "count",
+ 'default': 1,
+ 'type': int}),
+
PORT_LIST: ArgumentPack(['--port'],
{"nargs": '+',
'dest':'ports',