stl_pcap.py example - how to transmit a pcap
authorimarom <[email protected]>
Wed, 17 Feb 2016 14:58:32 +0000 (09:58 -0500)
committerimarom <[email protected]>
Wed, 17 Feb 2016 14:58:32 +0000 (09:58 -0500)
scripts/automation/trex_control_plane/stl/examples/stl_pcap.py [new file with mode: 0644]
scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py
scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py
scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py
scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/parsing_opts.py

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 (file)
index 0000000..a729a57
--- /dev/null
@@ -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()
+
index 46d33e3..fe16209 100644 (file)
@@ -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)
index c788e27..e028d6d 100644 (file)
@@ -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)
 
index 130beab..b72b5d3 100644 (file)
@@ -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)
index 84dd509..92e9a1d 100755 (executable)
@@ -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',