Browse Source

Merge branch 'develop' of https://git.tk.informatik.tu-darmstadt.de/leon.boeck/ID2T-toolkit-BotnetTraffic into develop

dustin.born 7 years ago
parent
commit
3229e7aaa7

+ 24 - 0
Dockerfile

@@ -0,0 +1,24 @@
+FROM debian:latest
+
+# install all the necessary packages (see readme.md, but libpcap-dev might not be on that list, it's still needed)
+RUN apt-get update && apt-get install -y --no-install-recommends build-essential cmake libboost-dev libboost-python-dev libtins-dev libpcap-dev python3-dev sqlite3 \
+	python3-pip python3-scapy python3-numpy python3-matplotlib python3-scipy python3-setuptools
+RUN pip3 install lea # for some reason you cant install lea via apt
+
+# make the required directored to copy the files into
+RUN mkdir /id2t /id2t/code /id2t/code_boost /id2t/resources
+WORKDIR /id2t
+
+# copy all the necessary files
+# there are multiple commands because docker only copies the directories' contents and not the directory itself and dont know what else to do here
+COPY build.sh /id2t/
+COPY code/ /id2t/code/
+COPY code_boost/ /id2t/code_boost/
+COPY resources /id2t/resources
+
+# run the build-script
+RUN ./build.sh
+
+# add id2t to the path
+ENV PATH="$PATH:/id2t"
+

+ 3 - 0
code/Attack/AttackParameters.py

@@ -50,6 +50,9 @@ class Parameter(Enum):
     IP_REUSE_EXTERNAL = 'ip.reuse.external'  # percentage of public IPs in original PCAP to be reused
     IP_REUSE_EXTERNAL = 'ip.reuse.external'  # percentage of public IPs in original PCAP to be reused
     # recommended type: Positive Integer between 0 and 100 ------------------------------------
     # recommended type: Positive Integer between 0 and 100 ------------------------------------
     PACKET_PADDING = 'packet.padding'
     PACKET_PADDING = 'packet.padding'
+    # calculate the destination port based on the hostname (like some botnets do)
+    # otherwise the destination port is a normal ephemeral port
+    BOTNET_DST_PORT_CALCULATION = "botnet.dstportcalculation"
 
 
 class ParameterTypes(Enum):
 class ParameterTypes(Enum):
     """
     """

+ 47 - 27
code/Attack/MembersMgmtCommAttack.py

@@ -109,7 +109,8 @@ class MembersMgmtCommAttack(BaseAttack.BaseAttack):
             Param.NAT_PRESENT: ParameterTypes.TYPE_BOOLEAN,
             Param.NAT_PRESENT: ParameterTypes.TYPE_BOOLEAN,
 
 
             # the base PCAP for the TTL distribution
             # the base PCAP for the TTL distribution
-            Param.TTL_FROM_CAIDA: ParameterTypes.TYPE_BOOLEAN
+            Param.TTL_FROM_CAIDA: ParameterTypes.TYPE_BOOLEAN,
+            Param.BOTNET_DST_PORT_CALCULATION: ParameterTypes.TYPE_BOOLEAN
         }
         }
 
 
         # create dict with MessageType values for fast name lookup
         # create dict with MessageType values for fast name lookup
@@ -154,6 +155,7 @@ class MembersMgmtCommAttack(BaseAttack.BaseAttack):
 
 
         # choose the input PCAP as default base for the TTL distribution
         # choose the input PCAP as default base for the TTL distribution
         self.add_param_value(Param.TTL_FROM_CAIDA, False)
         self.add_param_value(Param.TTL_FROM_CAIDA, False)
+        self.add_param_value(Param.BOTNET_DST_PORT_CALCULATION, True)
 
 
 
 
     def generate_attack_pcap(self, context):
     def generate_attack_pcap(self, context):
@@ -178,6 +180,7 @@ class MembersMgmtCommAttack(BaseAttack.BaseAttack):
         limit_packetcount = self.get_param_value(Param.PACKETS_LIMIT)
         limit_packetcount = self.get_param_value(Param.PACKETS_LIMIT)
         limit_duration = self.get_param_value(Param.ATTACK_DURATION)
         limit_duration = self.get_param_value(Param.ATTACK_DURATION)
         path_attack_pcap = None
         path_attack_pcap = None
+        overThousand = False
 
 
         msg_packet_mapping = MessageMapping(messages)
         msg_packet_mapping = MessageMapping(messages)
 
 
@@ -220,18 +223,33 @@ class MembersMgmtCommAttack(BaseAttack.BaseAttack):
             if total_pkts <= 1:
             if total_pkts <= 1:
                 self.attack_start_utime = packets[0].time
                 self.attack_start_utime = packets[0].time
             elif total_pkts % BUFFER_SIZE == 0: # every 1000 packets write them to the PCAP file (append)
             elif total_pkts % BUFFER_SIZE == 0: # every 1000 packets write them to the PCAP file (append)
-                packets = list(packets)
-                Generator.equal_length(packets, padding = padding)
-                last_packet = packets[-1]
-                path_attack_pcap = self.write_attack_pcap(packets, True, path_attack_pcap)
-                packets = deque(maxlen=BUFFER_SIZE)
+                if overThousand: # if over 1000 packets written, there may be a different packet-length for the last few packets 
+                    packets = list(packets)
+                    Generator.equal_length(packets, length = max_len, padding = padding, force_len = True)
+                    last_packet = packets[-1]
+                    path_attack_pcap = self.write_attack_pcap(packets, True, path_attack_pcap)
+                    packets = deque(maxlen=BUFFER_SIZE)
+                else:
+                    packets = list(packets)
+                    Generator.equal_length(packets, padding = padding)
+                    last_packet = packets[-1]
+                    max_len = len(last_packet)
+                    overThousand = True
+                    path_attack_pcap = self.write_attack_pcap(packets, True, path_attack_pcap)
+                    packets = deque(maxlen=BUFFER_SIZE)
 
 
         # if there are unwritten packets remaining, write them to the PCAP file
         # if there are unwritten packets remaining, write them to the PCAP file
         if len(packets) > 0:
         if len(packets) > 0:
-            packets = list(packets)
-            Generator.equal_length(packets, padding = padding)
-            path_attack_pcap = self.write_attack_pcap(packets, True, path_attack_pcap)
-            last_packet = packets[-1]
+            if overThousand:
+                packets = list(packets)
+                Generator.equal_length(packets, length = max_len, padding = padding, force_len = True)
+                path_attack_pcap = self.write_attack_pcap(packets, True, path_attack_pcap)
+                last_packet = packets[-1]
+            else:
+                packets = list(packets)
+                Generator.equal_length(packets, padding = padding)
+                path_attack_pcap = self.write_attack_pcap(packets, True, path_attack_pcap)
+                last_packet = packets[-1]
 
 
         # write the mapping to a file
         # write the mapping to a file
         msg_packet_mapping.write_to(context.allocate_file("_mapping.xml"))
         msg_packet_mapping.write_to(context.allocate_file("_mapping.xml"))
@@ -293,12 +311,11 @@ class MembersMgmtCommAttack(BaseAttack.BaseAttack):
             else:
             else:
                 return 0
                 return 0
 
 
-        def assign_realistic_ttls(bot_configs):
+        def assign_realistic_ttls(bot_configs:list):
             '''
             '''
             Assigns a realisitic ttl to each bot from @param: bot_configs. Uses statistics and distribution to be able
             Assigns a realisitic ttl to each bot from @param: bot_configs. Uses statistics and distribution to be able
             to calculate a realisitc ttl.
             to calculate a realisitc ttl.
-            :param bot_configs:
-            :return:
+            :param bot_configs: List that contains all bots that should be assigned with realistic ttls.
             '''
             '''
             ids = sorted(bot_configs.keys())
             ids = sorted(bot_configs.keys())
             for pos,bot in enumerate(ids):
             for pos,bot in enumerate(ids):
@@ -318,7 +335,7 @@ class MembersMgmtCommAttack(BaseAttack.BaseAttack):
         def assign_realistic_timestamps(messages: list, external_ids: set, local_ids: set, avg_delay_local:float, avg_delay_external: float, zero_reference:float):
         def assign_realistic_timestamps(messages: list, external_ids: set, local_ids: set, avg_delay_local:float, avg_delay_external: float, zero_reference:float):
             """
             """
             Assigns realistic timestamps to a set of messages
             Assigns realistic timestamps to a set of messages
-            
+
             :param messages: the set of messages to be updated
             :param messages: the set of messages to be updated
             :param external_ids: the set of bot ids, that are outside the network, i.e. external
             :param external_ids: the set of bot ids, that are outside the network, i.e. external
             :param local_ids: the set of bot ids, that are inside the network, i.e. local
             :param local_ids: the set of bot ids, that are inside the network, i.e. local
@@ -330,7 +347,7 @@ class MembersMgmtCommAttack(BaseAttack.BaseAttack):
             last_response = {}      # Dict, takes a tuple of 2 Bot_IDs as a key (requester, responder), returns the time of the last response, the requester received
             last_response = {}      # Dict, takes a tuple of 2 Bot_IDs as a key (requester, responder), returns the time of the last response, the requester received
                                     # necessary in order to make sure, that additional requests are sent only after the response to the last one was received
                                     # necessary in order to make sure, that additional requests are sent only after the response to the last one was received
             for msg in messages:    # init
             for msg in messages:    # init
-                last_response[(msg.src, msg.dst)] = -1  
+                last_response[(msg.src, msg.dst)] = -1
 
 
             # update all timestamps
             # update all timestamps
             for req_msg in messages:
             for req_msg in messages:
@@ -356,7 +373,7 @@ class MembersMgmtCommAttack(BaseAttack.BaseAttack):
                     if req_msg.src in external_ids or req_msg.dst in external_ids:
                     if req_msg.src in external_ids or req_msg.dst in external_ids:
                         #external communication
                         #external communication
                         respns_msg.time = req_msg.time + avg_delay_external + uniform(-0.1*avg_delay_external, 0.1*avg_delay_external)
                         respns_msg.time = req_msg.time + avg_delay_external + uniform(-0.1*avg_delay_external, 0.1*avg_delay_external)
-                    
+
                     else:
                     else:
                         #local communication
                         #local communication
                         respns_msg.time = req_msg.time + avg_delay_local + uniform(-0.1*avg_delay_local, 0.1*avg_delay_local)
                         respns_msg.time = req_msg.time + avg_delay_local + uniform(-0.1*avg_delay_local, 0.1*avg_delay_local)
@@ -384,12 +401,12 @@ class MembersMgmtCommAttack(BaseAttack.BaseAttack):
                 with open("resources/CaidaTTL_perIP.csv", "r") as file:
                 with open("resources/CaidaTTL_perIP.csv", "r") as file:
                     # every line consists of: IP, TTL, Frequency
                     # every line consists of: IP, TTL, Frequency
                     next(file)  # skip CSV header line
                     next(file)  # skip CSV header line
-                    for line in file: 
+                    for line in file:
                         ip_addr, ttl, freq = line.split(",")
                         ip_addr, ttl, freq = line.split(",")
                         if ip_addr not in ip_based_distrib:
                         if ip_addr not in ip_based_distrib:
                             ip_based_distrib[ip_addr] = {}  # the values for ip_based_distrib are dicts with key=TTL, value=Frequency
                             ip_based_distrib[ip_addr] = {}  # the values for ip_based_distrib are dicts with key=TTL, value=Frequency
                         ip_based_distrib[ip_addr][ttl] = int(freq)
                         ip_based_distrib[ip_addr][ttl] = int(freq)
-                        
+
                 return ip_based_distrib
                 return ip_based_distrib
 
 
             def get_total_ttl_distrib():
             def get_total_ttl_distrib():
@@ -402,12 +419,12 @@ class MembersMgmtCommAttack(BaseAttack.BaseAttack):
                 with open("resources/CaidaTTL_total.csv", "r") as file:
                 with open("resources/CaidaTTL_total.csv", "r") as file:
                     # every line consists of: TTL, Frequency, Fraction
                     # every line consists of: TTL, Frequency, Fraction
                     next(file)  # skip CSV header line
                     next(file)  # skip CSV header line
-                    for line in file: 
+                    for line in file:
                         ttl, freq, _ = line.split(",")
                         ttl, freq, _ = line.split(",")
                         total_ttl_distrib[ttl] = int(freq)
                         total_ttl_distrib[ttl] = int(freq)
-                        
+
                 return total_ttl_distrib
                 return total_ttl_distrib
-            
+
             # get the TTL distribution for every IP that is available in "resources/CaidaTTL_perIP.csv"
             # get the TTL distribution for every IP that is available in "resources/CaidaTTL_perIP.csv"
             ip_ttl_distrib = get_ip_ttl_distrib()
             ip_ttl_distrib = get_ip_ttl_distrib()
             # build a probability dict for the total TTL distribution
             # build a probability dict for the total TTL distribution
@@ -422,7 +439,7 @@ class MembersMgmtCommAttack(BaseAttack.BaseAttack):
                     bot_configs[bot_id]["TTL"] = 128
                     bot_configs[bot_id]["TTL"] = 128
 
 
                 # if there exists detailed information about the TTL distribution of this IP
                 # if there exists detailed information about the TTL distribution of this IP
-                elif bot_ip in ip_ttl_distrib:  
+                elif bot_ip in ip_ttl_distrib:
                     ip_ttl_freqs = ip_ttl_distrib[bot_ip]
                     ip_ttl_freqs = ip_ttl_distrib[bot_ip]
                     source_ttl_prob_dict = Lea.fromValFreqsDict(ip_ttl_freqs)  # build a probability dict from this IP's TTL distribution
                     source_ttl_prob_dict = Lea.fromValFreqsDict(ip_ttl_freqs)  # build a probability dict from this IP's TTL distribution
                     bot_configs[bot_id]["TTL"] = source_ttl_prob_dict.random()
                     bot_configs[bot_id]["TTL"] = source_ttl_prob_dict.random()
@@ -519,6 +536,8 @@ class MembersMgmtCommAttack(BaseAttack.BaseAttack):
             reuse_count_external = int(reuse_percent_total * reuse_percent_external * number_external_ids)
             reuse_count_external = int(reuse_percent_total * reuse_percent_external * number_external_ids)
             existing_external_ips = sorted(pcapops.get_existing_external_ips(reuse_count_external))
             existing_external_ips = sorted(pcapops.get_existing_external_ips(reuse_count_external))
             remaining = len(external_ids) - len(existing_external_ips)
             remaining = len(external_ids) - len(existing_external_ips)
+
+            for external_ip in existing_external_ips: ipgen.add_to_blacklist(external_ip)
             new_external_ips = sorted([ipgen.random_ip() for _ in range(remaining)])
             new_external_ips = sorted([ipgen.random_ip() for _ in range(remaining)])
             add_ids_to_config(sorted(external_ids), existing_external_ips, new_external_ips, bot_configs, idtype="external", router_mac=router_mac)
             add_ids_to_config(sorted(external_ids), existing_external_ips, new_external_ips, bot_configs, idtype="external", router_mac=router_mac)
 
 
@@ -534,12 +553,13 @@ class MembersMgmtCommAttack(BaseAttack.BaseAttack):
 
 
         portSelector = PortSelectors.LINUX
         portSelector = PortSelectors.LINUX
         # create port configurations for the bots
         # create port configurations for the bots
-        for bot in bot_configs:
+        calculate_dst_port = self.get_param_value(Param.BOTNET_DST_PORT_CALCULATION)
+        for bot in sorted(bot_configs):
             bot_configs[bot]["SrcPort"] = portSelector.select_port_udp()
             bot_configs[bot]["SrcPort"] = portSelector.select_port_udp()
-            bot_configs[bot]["DstPort"] = Generator.gen_random_server_port()
-
-        # print(local_init_ids)
-        # print(bot_configs)
+            if calculate_dst_port:
+                bot_configs[bot]["DstPort"] = Generator.gen_random_server_port()
+            else:
+                bot_configs[bot]["DstPort"] = portSelector.select_port_udp()
 
 
         # assign realistic TTL for every bot
         # assign realistic TTL for every bot
         if self.get_param_value(Param.TTL_FROM_CAIDA):
         if self.get_param_value(Param.TTL_FROM_CAIDA):

+ 10 - 1
code/CLI.py

@@ -68,6 +68,9 @@ class CLI(object):
         parser.add_argument('-o', '--output', metavar="PCAP_FILE",
         parser.add_argument('-o', '--output', metavar="PCAP_FILE",
                                  help='path to the output pcap file')
                                  help='path to the output pcap file')
 
 
+        parser.add_argument('-ie', '--inject_empty', action='store_true',
+                                       help='injects ATTACK into an EMPTY PCAP file, using the statistics of the input PCAP.')
+
         # Attack arguments
         # Attack arguments
         parser.add_argument('-a', '--attack', metavar="ATTACK", action='append',
         parser.add_argument('-a', '--attack', metavar="ATTACK", action='append',
                                        help='injects ATTACK into a PCAP file.', nargs='+')
                                        help='injects ATTACK into a PCAP file.', nargs='+')
@@ -162,7 +165,12 @@ class CLI(object):
         # Process attack(s) with given attack params
         # Process attack(s) with given attack params
         if self.args.attack is not None:
         if self.args.attack is not None:
             # If attack is present, load attack with params
             # If attack is present, load attack with params
-            controller.process_attacks(self.args.attack)
+            if self.args.inject_empty:
+                # Attack PCAPs will not be merged with base PCAP
+                controller.process_attacks(self.args.attack, inject_empty=True)
+            else:
+                # Attack PCAP will be merged with base PCAP
+                controller.process_attacks(self.args.attack)
 
 
         # Parameter -q without arguments was given -> go into query loop
         # Parameter -q without arguments was given -> go into query loop
         if self.args.query == [None]:
         if self.args.query == [None]:
@@ -184,3 +192,4 @@ def main(args):
 # Uncomment to enable calling by terminal
 # Uncomment to enable calling by terminal
 if __name__ == '__main__':
 if __name__ == '__main__':
     main(sys.argv[1:])
     main(sys.argv[1:])
+

+ 5 - 0
code/ID2TLib/Botnet/MessageMapping.py

@@ -1,5 +1,6 @@
 import os.path
 import os.path
 from xml.dom.minidom import *
 from xml.dom.minidom import *
+import datetime
 
 
 
 
 class MessageMapping:
 class MessageMapping:
@@ -33,7 +34,11 @@ class MessageMapping:
             mapping.setAttribute("Src", str(message.src["ID"]))
             mapping.setAttribute("Src", str(message.src["ID"]))
             mapping.setAttribute("Dst", str(message.dst["ID"]))
             mapping.setAttribute("Dst", str(message.dst["ID"]))
             mapping.setAttribute("Type", str(message.type.value))
             mapping.setAttribute("Type", str(message.type.value))
+
+            dt = datetime.datetime.fromtimestamp(message.time)
             mapping.setAttribute("Time", str(message.time))
             mapping.setAttribute("Time", str(message.time))
+            mapping.setAttribute("Time-Datetime", dt.strftime("%Y-%m-%d %H:%M:%S.") + str(dt.microsecond))
+            mapping.setAttribute("Time-Timeonly", dt.strftime("%H:%M:%S.") + str(dt.microsecond))
 
 
             packet = self.id_to_packet.get(message.msg_id)
             packet = self.id_to_packet.get(message.msg_id)
             mapping.setAttribute(self.ATTR_HAS_PACKET, "true" if packet is not None else "false")
             mapping.setAttribute(self.ATTR_HAS_PACKET, "true" if packet is not None else "false")

+ 5 - 1
code/ID2TLib/CommunicationProcessor.py

@@ -125,6 +125,9 @@ class CommunicationProcessor():
         msgs, msg_id = [], 0
         msgs, msg_id = [], 0
         # keep track of previous request to find connections
         # keep track of previous request to find connections
         prev_reqs = {}
         prev_reqs = {}
+        # used to determine whether a request has been seen yet, so that replies before the first request are skipped and do not throw an error by
+        # accessing the empty dict prev_reqs (this is not a perfect solution, but it works most of the time)
+        req_seen = False
         local_init_ids = self.local_init_ids
         local_init_ids = self.local_init_ids
         external_init_ids = set()
         external_init_ids = set()
 
 
@@ -154,9 +157,10 @@ class CommunicationProcessor():
                 msgs.append(msg)
                 msgs.append(msg)
                 prev_reqs[msg_str] = msg_id
                 prev_reqs[msg_str] = msg_id
                 msg_id += 1
                 msg_id += 1
+                req_seen = True
 
 
             # process a reply
             # process a reply
-            elif msg_type in {MessageType.SALITY_HELLO_REPLY, MessageType.SALITY_NL_REPLY}:
+            elif msg_type in {MessageType.SALITY_HELLO_REPLY, MessageType.SALITY_NL_REPLY} and req_seen:
                 if not self.nat and id_src in local_init_ids and id_dst not in local_init_ids:
                 if not self.nat and id_src in local_init_ids and id_dst not in local_init_ids:
                     # process ID's role
                     # process ID's role
                     external_init_ids.add(id_dst)
                     external_init_ids.add(id_dst)

+ 20 - 7
code/ID2TLib/Controller.py

@@ -1,6 +1,7 @@
 import os
 import os
 import sys
 import sys
 import shutil
 import shutil
+import time
 
 
 from ID2TLib.AttackController import AttackController
 from ID2TLib.AttackController import AttackController
 from ID2TLib.LabelManager import LabelManager
 from ID2TLib.LabelManager import LabelManager
@@ -45,14 +46,15 @@ class Controller:
         """
         """
         self.statistics.load_pcap_statistics(flag_write_file, flag_recalculate_stats, flag_print_statistics)
         self.statistics.load_pcap_statistics(flag_write_file, flag_recalculate_stats, flag_print_statistics)
 
 
-    def process_attacks(self, attacks_config: list):
+    def process_attacks(self, attacks_config: list, inject_empty: bool=False):
         """
         """
         Creates the attack based on the attack name and the attack parameters given in the attacks_config. The
         Creates the attack based on the attack name and the attack parameters given in the attacks_config. The
         attacks_config is a list of attacks, e.g.
         attacks_config is a list of attacks, e.g.
         [['PortscanAttack', 'ip.src="192.168.178.2",'dst.port=80'],['PortscanAttack', 'ip.src="10.10.10.2"]].
         [['PortscanAttack', 'ip.src="192.168.178.2",'dst.port=80'],['PortscanAttack', 'ip.src="10.10.10.2"]].
         Merges the individual temporary attack pcaps into one single pcap and merges this single pcap with the
         Merges the individual temporary attack pcaps into one single pcap and merges this single pcap with the
-        input dataset.
+        input dataset if desired.
         :param attacks_config: A list of attacks with their attack parameters.
         :param attacks_config: A list of attacks with their attack parameters.
+        :param inject_empty: if flag is set, Attack PCAPs will not be merged with the base PCAP, ie. Attacks are injected into an empty PCAP
         """
         """
 
 
         # get output directory
         # get output directory
@@ -85,12 +87,23 @@ class Controller:
         else:
         else:
             attacks_pcap_path = self.written_pcaps[0]
             attacks_pcap_path = self.written_pcaps[0]
 
 
-        # merge single attack pcap with all attacks into base pcap
-        print("Merging base pcap with single attack pcap...", end=" ")
-        sys.stdout.flush()  # force python to print text immediately
+        if inject_empty:
+            # copy the attack pcap to the directory of the base PCAP instead of merging them
+            print("Copy single attack pcap to location of base pcap...", end=" ")
+            sys.stdout.flush()  # force python to print text immediately
+
+            timestamp = time.strftime("%Y%m%d") + '-' + time.strftime("%X").replace(':', '')
+            self.pcap_dest_path = self.pcap_src_path.replace(".pcap", timestamp + '.pcap')
+            shutil.copy(attacks_pcap_path, self.pcap_dest_path)
+
+        else:
+            # merge single attack pcap with all attacks into base pcap
+            print("Merging base pcap with single attack pcap...", end=" ")
+            sys.stdout.flush()  # force python to print text immediately
+
+            # cp merged PCAP to output path
+            self.pcap_dest_path = self.pcap_file.merge_attack(attacks_pcap_path)
 
 
-        # cp merged PCAP to output path
-        self.pcap_dest_path = self.pcap_file.merge_attack(attacks_pcap_path)
         if self.pcap_out_path:
         if self.pcap_out_path:
             if not self.pcap_out_path.endswith(".pcap"):
             if not self.pcap_out_path.endswith(".pcap"):
                 self.pcap_out_path += ".pcap"
                 self.pcap_out_path += ".pcap"

+ 2 - 2
code/ID2TLib/FileUtils.py

@@ -6,7 +6,7 @@ def parse_xml(filepath: str):
 	'''
 	'''
 	Parses an XML File
 	Parses an XML File
 	It is assumed, that packets are placed on the second hierarchical level and packetinformation is encoded as attributes
 	It is assumed, that packets are placed on the second hierarchical level and packetinformation is encoded as attributes
-	
+
 	:param filepath: the path to the XML file to be parsed
 	:param filepath: the path to the XML file to be parsed
 	:return: a List of Dictionaries, each Dictionary contains the information of one packet
 	:return: a List of Dictionaries, each Dictionary contains the information of one packet
 	'''
 	'''
@@ -24,7 +24,7 @@ def parse_xml(filepath: str):
 def parse_csv_to_xml(filepath: str):
 def parse_csv_to_xml(filepath: str):
 	'''
 	'''
 	Converts a CSV file into an XML file. Every entry is converted to a child with respective attributes of the root node
 	Converts a CSV file into an XML file. Every entry is converted to a child with respective attributes of the root node
-	
+
 	:param filepath: the path to the CSV file to be parsed
 	:param filepath: the path to the CSV file to be parsed
 	:return: a path to the newly created XML file
 	:return: a path to the newly created XML file
 	'''
 	'''

+ 26 - 21
code/ID2TLib/Generator.py

@@ -17,18 +17,18 @@ from . import IPv4 as ip
 '''PaddingGenerator
 '''PaddingGenerator
 '''
 '''
 
 
-def add_padding(packet, bytes_padding = 0, user_padding=True, rnd = False):
+def add_padding(packet, bytes_padding:int = 0, user_padding:bool=True, rnd:bool = False):
     '''
     '''
-    Adds padding to a packet with the given amount of bytes, but a maximum of 100 bytes.
+    Adds padding to a packet with the given amount of bytes, but a maximum of 100 bytes, if called by the user.
     :param packet: the packet that will be extended with the additional payload
     :param packet: the packet that will be extended with the additional payload
-    :param bytes_padding: the amount of bytes that will be appended to the packet
-    :param user_padding: true, if the function add_padding is called from another class and the user
-    sets the padding manually
-    :param rnd: adds a random padding betwing 0 and bytes_adding, if true
+    :param bytes_padding: the amount of bytes that will be appended to the packet. Capped to 100,
+    if called by the user.
+    :param user_padding: true, if the function add_padding by the user and not within the code
+    :param rnd: adds a random padding between 0 and bytes_padding, if true
     :return: the initial packet, extended with the wanted amount of bytes of padding
     :return: the initial packet, extended with the wanted amount of bytes of padding
     '''
     '''
 
 
-    if(user_padding and bytes_padding > 100):
+    if(user_padding == True and bytes_padding > 100):
         bytes_padding = 100
         bytes_padding = 100
 
 
     if (rnd is True):
     if (rnd is True):
@@ -38,26 +38,31 @@ def add_padding(packet, bytes_padding = 0, user_padding=True, rnd = False):
     packet[Raw].load += Raw(load=payload).load
     packet[Raw].load += Raw(load=payload).load
     return packet
     return packet
 
 
-def equal_length(list_of_packets, length = 0, padding = 0):
+def equal_length(list_of_packets:list, length:int = 0, padding:int = 0, force_len:bool = False):
     '''
     '''
-    Equals the length of a given set of packets on the given length. If the given length is smaller than the largest
-    packet, all the other packets are extended to the largest packet's length.
+    Equals the length of all packets of a given list of packets to the given length. If the given length is smaller than the largest
+    packet, all the other packets are extended to the largest packet's length. Add additional padding
+    afterwards to create realism.
     :param list_of_packets: The given set of packet.
     :param list_of_packets: The given set of packet.
-    :param length: The length each packet should have.
-    :return: The set of extended packets.
+    :param length: The length each packet should have. Can be redundant, if the largest packet has more bytes
+    :param force_len: if true, all packets are forced to take on the length of param length
+    than length.
+    :return: The list of extended packets.
     '''
     '''
-
-    largest_packet = length
-    for packet in list_of_packets:
-        packet_length = len(packet)
-        if(packet_length > largest_packet):
-            largest_packet = packet_length
+    if not force_len:
+        largest_packet = length
+        for packet in list_of_packets:
+            packet_length = len(packet)
+            if(packet_length > largest_packet):
+                largest_packet = packet_length
+    else:
+        largest_packet = length
 
 
     for packet in list_of_packets:
     for packet in list_of_packets:
         bytes_padding = largest_packet - len(packet)
         bytes_padding = largest_packet - len(packet)
         if(bytes_padding > 0):
         if(bytes_padding > 0):
-            add_padding(packet, bytes_padding, False, False)
-            add_padding(packet, padding, False, True)
+            add_padding(packet, bytes_padding, False, False) #Add padding to extend to param:length
+            add_padding(packet, padding, False, True) #Add random additional padding to create realism
 
 
     return list_of_packets
     return list_of_packets
 
 
@@ -390,4 +395,4 @@ class MappingIPGenerator(IPGenerator):
         return self.mapping[key]
         return self.mapping[key]
 
 
     def __getitem__(self, item):
     def __getitem__(self, item):
-        return self.get_mapped_ip(item)
+        return self.get_mapped_ip(item)

+ 96 - 1
code/ID2TLib/Statistics.py

@@ -578,6 +578,46 @@ class Statistics:
 
 
         return out_degree
         return out_degree
 
 
+    def get_overall_degree(self):
+        """
+        determines the overall-degree for each ipAddress, i.e. for every IP the count of ipAddresses it has sent packets to
+        :return: a list, each entry consists of one IPAddress and its associated overall-degree
+        """
+
+        out_degrees = self.get_out_degree()
+        in_degrees = self.get_in_degree()
+        overall_degrees = []
+        processed = {} # Dict, taking an IP Address and returning True, if the IP has already been processed and added to overall_degree
+
+        # initialize values of the dict for in_degrees, this is important for error-free checking whether there are not processed IPs
+        # for out_degrees this can be done without an additional loop
+        for inD in in_degrees:
+            processed[inD[0]] = False
+
+        for outD in out_degrees:
+            ip_out = outD[0]
+            processed[ip_out] = False
+
+            # add the sum of degrees for all IPs that appear in both lists
+            for inD in in_degrees:
+                ip_in = inD[0]
+                if ip_out == ip_in:
+                    # same IPAddress -> append sum of degrees
+                    overall_degrees.append((ip_out, outD[1] + inD[1]))
+                    processed[ip_out] = True
+
+            if not processed[ip_out]:
+                # if IP only appears in out_degree list -> just append the value
+                overall_degrees.append(outD)
+                processed[outD[0]] = True
+        
+        # add remaining IPs, which did not appear in out_degree
+        for inD in in_degrees:
+            if not processed[inD[0]]:
+                overall_degrees.append(inD)
+
+        return overall_degrees
+
     def filter_multiples(self, entries):
     def filter_multiples(self, entries):
         """
         """
         helper function, for get_out_degree and get_in_degree
         helper function, for get_out_degree and get_in_degree
@@ -598,7 +638,6 @@ class Statistics:
                     filtered_entries.append((p1[0], p1[1] + p2[1]))
                     filtered_entries.append((p1[0], p1[1] + p2[1]))
                     done.append(p1)
                     done.append(p1)
                     done.append(p2)
                     done.append(p2)
-                    # print("duplicate found:", p1, " and ", p2)
                     added = True
                     added = True
                     break
                     break
 
 
@@ -1143,6 +1182,61 @@ class Statistics:
             else:
             else:
                 print("Error: No statistics Information for plotting out-degrees found")
                 print("Error: No statistics Information for plotting out-degrees found")
 
 
+        def plot_overall_degree(file_ending: str):
+            """
+            Creates a Plot, visualizing the overall-degree for every IP Address
+
+            :param file_ending: The file extension for the output file containing the plot, e.g. "pdf"
+            :return: A filepath to the file containing the created plot
+            """
+
+            plt.gcf().clear()
+
+            # retrieve data
+            overall_degree = self.get_overall_degree()
+
+            if(overall_degree):
+                graphx, graphy = [], []
+                for entry in overall_degree:
+                    # degree values
+                    graphx.append(entry[1])
+                    # IP labels
+                    graphy.append(entry[0])
+
+                # set labels
+                plt.title("Overalldegree per IP Address")
+                plt.ylabel('IpAddress')
+                plt.xlabel('Overalldegree')
+
+                #set width of the bars
+                width = 0.3
+
+                # set scalings
+                plt.figure(figsize=(int(len(graphx))/20 + 5, int(len(graphy)/5) + 5))  # these proportions just worked well
+
+                #set limits of the axis
+                plt.ylim([0, len(graphy)])
+                plt.xlim([0, max(graphx) + 10])
+
+                # display numbers at each bar
+                for i, v in enumerate(graphx):
+                    plt.text(v + 1, i + .1, str(v), color='blue', fontweight='bold')
+
+                # display grid for better visuals
+                plt.grid(True)
+
+                # plot the bar
+                labels = graphy
+                graphy = list(range(len(graphx)))
+                plt.barh(graphy, graphx, width, align='center', linewidth=1, color='red', edgecolor='red')
+                plt.yticks(graphy, labels)
+                out = self.pcap_filepath.replace('.pcap', '_overall_degree' + file_ending)
+                plt.tight_layout()
+                plt.savefig(out,dpi=500)
+                return out
+            else:
+                print("Error: No statistics Information for plotting overall-degrees found")
+
         def plot_big_comm_interval_stat(attr:str, table:str, title:str, xlabel:str, suffix:str):
         def plot_big_comm_interval_stat(attr:str, table:str, title:str, xlabel:str, suffix:str):
             """
             """
             Plots the desired statistc per connection as horizontal bar plot. 
             Plots the desired statistc per connection as horizontal bar plot. 
@@ -1320,6 +1414,7 @@ class Statistics:
         plot_packets_per_connection_out = plot_packets_per_connection('.' + format)
         plot_packets_per_connection_out = plot_packets_per_connection('.' + format)
         plot_out_degree = plot_out_degree('.' + format)
         plot_out_degree = plot_out_degree('.' + format)
         plot_in_degree = plot_in_degree('.' + format)
         plot_in_degree = plot_in_degree('.' + format)
+        plot_overall_degree = plot_overall_degree('.' + format)
         plot_avg_pkts_per_comm_interval_out = plot_avg_pkts_per_comm_interval('.' + format)
         plot_avg_pkts_per_comm_interval_out = plot_avg_pkts_per_comm_interval('.' + format)
         plot_avg_time_between_comm_interval_out = plot_avg_time_between_comm_interval('.' + format)
         plot_avg_time_between_comm_interval_out = plot_avg_time_between_comm_interval('.' + format)
         plot_avg_comm_interval_time_out = plot_avg_comm_interval_time("." + format)
         plot_avg_comm_interval_time_out = plot_avg_comm_interval_time("." + format)

+ 430 - 0
resources/testcsv.csv

@@ -0,0 +1,430 @@
+Src: 1, Dst: 2, Type: 103, Time: 756.1045
+Src: 1, Dst: 3, Type: 103, Time: 756.1045
+Src: 2, Dst: 1, Type: 104, Time: 756.2045
+Src: 3, Dst: 1, Type: 104, Time: 756.3045
+Src: 1, Dst: 10, Type: 103, Time: 756.4045
+Src: 1, Dst: 15, Type: 103, Time: 756.4045
+Src: 1, Dst: 28, Type: 103, Time: 756.4045
+Src: 1, Dst: 12, Type: 103, Time: 756.4045
+Src: 1, Dst: 39, Type: 103, Time: 756.4045
+Src: 1, Dst: 159, Type: 103, Time: 756.4045
+Src: 10, Dst: 1, Type: 104, Time: 756.5045
+Src: 15, Dst: 1, Type: 104, Time: 756.5045
+Src: 28, Dst: 1, Type: 104, Time: 756.5045
+Src: 12, Dst: 1, Type: 104, Time: 756.5045
+Src: 39, Dst: 1, Type: 104, Time: 756.5045
+Src: 159, Dst: 1, Type: 3, Time: 756.8045
+Src: 2, Dst: 45, Type: 103, Time: 756.5045
+Src: 2, Dst: 81, Type: 103, Time: 756.5045
+Src: 2, Dst: 57, Type: 103, Time: 756.5045
+Src: 2, Dst: 64, Type: 103, Time: 756.5045
+Src: 2, Dst: 52, Type: 103, Time: 756.5045
+Src: 2, Dst: 11, Type: 103, Time: 756.5045
+Src: 45, Dst: 2, Type: 104, Time: 756.6045
+Src: 81, Dst: 2, Type: 104, Time: 756.6045
+Src: 57, Dst: 2, Type: 104, Time: 756.6045
+Src: 64, Dst: 2, Type: 104, Time: 756.6045
+Src: 52, Dst: 2, Type: 104, Time: 756.6045
+Src: 11, Dst: 2, Type: 3, Time: 756.9045
+Src: 3, Dst: 73, Type: 103, Time: 756.6045
+Src: 3, Dst: 219, Type: 103, Time: 756.6045
+Src: 3, Dst: 142, Type: 103, Time: 756.6045
+Src: 3, Dst: 232, Type: 103, Time: 756.6045
+Src: 3, Dst: 115, Type: 103, Time: 756.6045
+Src: 3, Dst: 94, Type: 103, Time: 756.6045
+Src: 73, Dst: 3, Type: 104, Time: 756.7045
+Src: 219, Dst: 3, Type: 104, Time: 756.7045
+Src: 142, Dst: 3, Type: 104, Time: 756.7045
+Src: 232, Dst: 3, Type: 104, Time: 756.7045
+Src: 115, Dst: 3, Type: 104, Time: 756.7045
+Src: 94, Dst: 3, Type: 3, Time: 757.0045
+Src: 1, Dst: 136, Type: 103, Time: 756.7045
+Src: 136, Dst: 1, Type: 104, Time: 756.8045
+Src: 1, Dst: 31, Type: 103, Time: 756.7045
+Src: 31, Dst: 1, Type: 104, Time: 756.8045
+Src: 2, Dst: 252, Type: 103, Time: 756.7045
+Src: 252, Dst: 2, Type: 104, Time: 756.8045
+Src: 2, Dst: 43, Type: 103, Time: 756.7045
+Src: 43, Dst: 2, Type: 104, Time: 756.8045
+Src: 3, Dst: 177, Type: 103, Time: 756.7045
+Src: 177, Dst: 3, Type: 104, Time: 756.8045
+Src: 3, Dst: 5, Type: 103, Time: 756.7045
+Src: 5, Dst: 3, Type: 104, Time: 756.8045
+Src: 10, Dst: 111, Type: 103, Time: 756.8045
+Src: 111, Dst: 10, Type: 104, Time: 756.9045
+Src: 10, Dst: 79, Type: 103, Time: 756.8045
+Src: 79, Dst: 10, Type: 104, Time: 756.9045
+Src: 15, Dst: 137, Type: 103, Time: 756.8045
+Src: 137, Dst: 15, Type: 104, Time: 756.9045
+Src: 15, Dst: 170, Type: 103, Time: 756.8045
+Src: 170, Dst: 15, Type: 104, Time: 756.9045
+Src: 28, Dst: 119, Type: 103, Time: 756.9045
+Src: 119, Dst: 28, Type: 104, Time: 757.0045
+Src: 28, Dst: 171, Type: 103, Time: 756.9045
+Src: 171, Dst: 28, Type: 104, Time: 757.0045
+Src: 12, Dst: 128, Type: 103, Time: 756.9045
+Src: 128, Dst: 12, Type: 104, Time: 757.0045
+Src: 12, Dst: 251, Type: 103, Time: 756.9045
+Src: 251, Dst: 12, Type: 104, Time: 757.0045
+Src: 39, Dst: 179, Type: 103, Time: 757.0045
+Src: 179, Dst: 39, Type: 104, Time: 757.1045
+Src: 39, Dst: 22, Type: 103, Time: 757.0045
+Src: 22, Dst: 39, Type: 104, Time: 757.1045
+Src: 45, Dst: 242, Type: 103, Time: 757.0045
+Src: 242, Dst: 45, Type: 104, Time: 757.1045
+Src: 45, Dst: 87, Type: 103, Time: 757.0045
+Src: 87, Dst: 45, Type: 104, Time: 757.1045
+Src: 81, Dst: 80, Type: 103, Time: 757.1045
+Src: 80, Dst: 81, Type: 104, Time: 757.2045
+Src: 81, Dst: 166, Type: 103, Time: 757.1045
+Src: 166, Dst: 81, Type: 104, Time: 757.2045
+Src: 57, Dst: 65, Type: 103, Time: 757.1045
+Src: 65, Dst: 57, Type: 104, Time: 757.2045
+Src: 57, Dst: 223, Type: 103, Time: 757.1045
+Src: 223, Dst: 57, Type: 104, Time: 757.2045
+Src: 64, Dst: 235, Type: 103, Time: 757.1045
+Src: 235, Dst: 64, Type: 104, Time: 757.2045
+Src: 64, Dst: 44, Type: 103, Time: 757.1045
+Src: 44, Dst: 64, Type: 104, Time: 757.2045
+Src: 52, Dst: 66, Type: 103, Time: 757.1045
+Src: 66, Dst: 52, Type: 104, Time: 757.2045
+Src: 52, Dst: 215, Type: 103, Time: 757.1045
+Src: 215, Dst: 52, Type: 104, Time: 757.2045
+Src: 73, Dst: 184, Type: 103, Time: 757.1045
+Src: 184, Dst: 73, Type: 104, Time: 757.2045
+Src: 73, Dst: 114, Type: 103, Time: 757.1045
+Src: 114, Dst: 73, Type: 104, Time: 757.2045
+Src: 219, Dst: 156, Type: 103, Time: 757.1045
+Src: 156, Dst: 219, Type: 104, Time: 757.2045
+Src: 219, Dst: 239, Type: 103, Time: 757.1045
+Src: 239, Dst: 219, Type: 104, Time: 757.2045
+Src: 142, Dst: 100, Type: 103, Time: 757.1045
+Src: 100, Dst: 142, Type: 104, Time: 757.2045
+Src: 142, Dst: 181, Type: 103, Time: 757.1045
+Src: 181, Dst: 142, Type: 104, Time: 757.2045
+Src: 232, Dst: 61, Type: 103, Time: 757.1045
+Src: 61, Dst: 232, Type: 104, Time: 757.2045
+Src: 232, Dst: 209, Type: 103, Time: 757.1045
+Src: 209, Dst: 232, Type: 104, Time: 757.2045
+Src: 115, Dst: 140, Type: 103, Time: 757.2045
+Src: 140, Dst: 115, Type: 104, Time: 757.3045
+Src: 115, Dst: 160, Type: 103, Time: 757.2045
+Src: 160, Dst: 115, Type: 104, Time: 757.3045
+Src: 1, Dst: 2, Type: 103, Time: 757.3045
+Src: 1, Dst: 3, Type: 103, Time: 757.3045
+Src: 1, Dst: 10, Type: 103, Time: 757.3045
+Src: 1, Dst: 15, Type: 103, Time: 757.3045
+Src: 1, Dst: 28, Type: 103, Time: 757.3045
+Src: 1, Dst: 12, Type: 103, Time: 757.3045
+Src: 1, Dst: 39, Type: 103, Time: 757.3045
+Src: 1, Dst: 136, Type: 103, Time: 757.3045
+Src: 1, Dst: 31, Type: 103, Time: 757.3045
+Src: 2, Dst: 1, Type: 104, Time: 757.4045
+Src: 3, Dst: 1, Type: 104, Time: 757.4045
+Src: 10, Dst: 1, Type: 104, Time: 757.4045
+Src: 15, Dst: 1, Type: 104, Time: 757.4045
+Src: 28, Dst: 1, Type: 104, Time: 757.4045
+Src: 12, Dst: 1, Type: 104, Time: 757.4045
+Src: 39, Dst: 1, Type: 104, Time: 757.4045
+Src: 136, Dst: , Type: 104, Time: 757.4045
+Src: 31, Dst: , Type: 104, Time: 757.4045
+Src: 2, Dst: 45, Type: 103, Time: 757.4045
+Src: 2, Dst: 81, Type: 103, Time: 757.4045
+Src: 2, Dst: 57, Type: 103, Time: 757.4045
+Src: 2, Dst: 64, Type: 103, Time: 757.4045
+Src: 2, Dst: 52, Type: 103, Time: 757.4045
+Src: 2, Dst: 252, Type: 103, Time: 757.4045
+Src: 2, Dst: 43, Type: 103, Time: 757.4045
+Src: 45, Dst: 2, Type: 104, Time: 757.5045
+Src: 81, Dst: 2, Type: 104, Time: 757.5045
+Src: 57, Dst: 2, Type: 104, Time: 757.5045
+Src: 64, Dst: 2, Type: 104, Time: 757.5045
+Src: 52, Dst: 2, Type: 104, Time: 757.5045
+Src: 252, Dst: 2, Type: 104, Time: 757.5045
+Src: 43, Dst: 2, Type: 104, Time: 757.5045
+Src: 3, Dst: 73, Type: 103, Time: 757.4045
+Src: 3, Dst: 219, Type: 103, Time: 757.4045
+Src: 3, Dst: 142, Type: 103, Time: 757.4045
+Src: 3, Dst: 232, Type: 103, Time: 757.4045
+Src: 3, Dst: 115, Type: 103, Time: 757.4045
+Src: 3, Dst: 177, Type: 103, Time: 757.4045
+Src: 3, Dst: 5, Type: 103, Time: 757.4045
+Src: 73, Dst: 3, Type: 104, Time: 757.5045
+Src: 219, Dst: 3, Type: 104, Time: 757.5045
+Src: 142, Dst: 3, Type: 104, Time: 757.5045
+Src: 232, Dst: 3, Type: 104, Time: 757.5045
+Src: 115, Dst: 3, Type: 104, Time: 757.5045
+Src: 94, Dst: 3, Type: 104, Time: 757.5045
+Src: 177, Dst: 3, Type: 104, Time: 757.5045
+Src: 10, Dst: 111, Type: 103, Time: 757.5045
+Src: 10, Dst: 79, Type: 103, Time: 757.5045
+Src: 111, Dst: 10, Type: 104, Time: 757.6045
+Src: 79, Dst: 10, Type: 104, Time: 757.6045
+Src: 15, Dst: 137, Type: 103, Time: 757.5045
+Src: 15, Dst: 170, Type: 103, Time: 757.5045
+Src: 137, Dst: 15, Type: 104, Time: 757.6045
+Src: 170, Dst: 15, Type: 104, Time: 757.6045
+Src: 28, Dst: 119, Type: 103, Time: 757.6045
+Src: 28, Dst: 171, Type: 103, Time: 757.6045
+Src: 119, Dst: 28, Type: 104, Time: 757.7045
+Src: 171, Dst: 28, Type: 104, Time: 757.7045
+Src: 12, Dst: 128, Type: 103, Time: 757.6045
+Src: 12, Dst: 251, Type: 103, Time: 757.6045
+Src: 128, Dst: 12, Type: 104, Time: 757.7045
+Src: 251, Dst: 12, Type: 104, Time: 757.7045
+Src: 39, Dst: 179, Type: 103, Time: 757.7045
+Src: 39, Dst: 22, Type: 103, Time: 757.7045
+Src: 179, Dst: 39, Type: 104, Time: 757.8045
+Src: 22, Dst: 39, Type: 104, Time: 757.8045
+Src: 45, Dst: 242, Type: 103, Time: 757.7045
+Src: 45, Dst: 87, Type: 103, Time: 757.7045
+Src: 242, Dst: 45, Type: 104, Time: 757.8045
+Src: 87, Dst: 45, Type: 104, Time: 757.8045
+Src: 81, Dst: 80, Type: 103, Time: 757.7045
+Src: 81, Dst: 166, Type: 103, Time: 757.7045
+Src: 80, Dst: 81, Type: 104, Time: 757.8045
+Src: 166, Dst: 81, Type: 104, Time: 757.8045
+Src: 57, Dst: 65, Type: 103, Time: 757.7045
+Src: 57, Dst: 223, Type: 103, Time: 757.7045
+Src: 65, Dst: 57, Type: 104, Time: 757.8045
+Src: 223, Dst: 57, Type: 104, Time: 757.8045
+Src: 64, Dst: 235, Type: 103, Time: 757.6045
+Src: 64, Dst: 44, Type: 103, Time: 757.6045
+Src: 235, Dst: 64, Type: 104, Time: 757.7045
+Src: 44, Dst: 64, Type: 104, Time: 757.7045
+Src: 52, Dst: 66, Type: 103, Time: 757.6045
+Src: 52, Dst: 215, Type: 103, Time: 757.6045
+Src: 66, Dst: 52, Type: 104, Time: 757.7045
+Src: 215, Dst: 52, Type: 104, Time: 757.7045
+Src: 73, Dst: 184, Type: 103, Time: 757.9045
+Src: 73, Dst: 114, Type: 103, Time: 757.9045
+Src: 184, Dst: 73, Type: 104, Time: 758.0045
+Src: 114, Dst: 73, Type: 104, Time: 758.0045
+Src: 219, Dst: 156, Type: 103, Time: 757.9045
+Src: 219, Dst: 239, Type: 103, Time: 757.9045
+Src: 156, Dst: 219, Type: 104, Time: 758.0045
+Src: 239, Dst: 219, Type: 104, Time: 758.0045
+Src: 142, Dst: 100, Type: 103, Time: 757.9045
+Src: 142, Dst: 181, Type: 103, Time: 757.9045
+Src: 100, Dst: 142, Type: 104, Time: 758.0045
+Src: 181, Dst: 142, Type: 104, Time: 758.0045
+Src: 232, Dst: 61, Type: 103, Time: 758.0045
+Src: 232, Dst: 209, Type: 103, Time: 758.0045
+Src: 61, Dst: 232, Type: 104, Time: 758.1045
+Src: 209, Dst: 232, Type: 104, Time: 758.1045
+Src: 115, Dst: 140, Type: 103, Time: 758.0045
+Src: 115, Dst: 160, Type: 103, Time: 758.0045
+Src: 140, Dst: 115, Type: 104, Time: 758.1045
+Src: 160, Dst: 115, Type: 104, Time: 758.1045
+Src: 1, Dst: 2, Type: 103, Time: 600757.3045
+Src: 1, Dst: 3, Type: 103, Time: 600757.3045
+Src: 1, Dst: 10, Type: 103, Time: 600757.3045
+Src: 1, Dst: 15, Type: 103, Time: 600757.3045
+Src: 1, Dst: 28, Type: 103, Time: 600757.3045
+Src: 1, Dst: 12, Type: 103, Time: 600757.3045
+Src: 1, Dst: 39, Type: 103, Time: 600757.3045
+Src: 1, Dst: 136, Type: 103, Time: 600757.3045
+Src: 1, Dst: 31, Type: 103, Time: 600757.3045
+Src: 2, Dst: 1, Type: 104, Time: 600757.4045
+Src: 3, Dst: 1, Type: 104, Time: 600757.4045
+Src: 10, Dst: 1, Type: 104, Time: 600757.4045
+Src: 15, Dst: 1, Type: 104, Time: 600757.4045
+Src: 28, Dst: 1, Type: 104, Time: 600757.4045
+Src: 12, Dst: 1, Type: 104, Time: 600757.4045
+Src: 39, Dst: 1, Type: 104, Time: 600757.4045
+Src: 136, Dst: , Type: 104, Time: 600757.4045
+Src: 31, Dst: , Type: 104, Time: 600757.4045
+Src: 1, Dst: 2, Type: 101, Time: 600757.5045
+Src: 1, Dst: 3, Type: 101, Time: 600757.5045
+Src: 1, Dst: 10, Type: 101, Time: 600757.5045
+Src: 1, Dst: 15, Type: 101, Time: 600757.5045
+Src: 1, Dst: 28, Type: 101, Time: 600757.5045
+Src: 1, Dst: 12, Type: 101, Time: 600757.5045
+Src: 1, Dst: 39, Type: 101, Time: 600757.5045
+Src: 1, Dst: 136, Type: 101, Time: 600757.5045
+Src: 1, Dst: 31, Type: 101, Time: 600757.5045
+Src: 2, Dst: 1, Type: 102, Time: 600757.6045
+Src: 3, Dst: 1, Type: 102, Time: 600757.6045
+Src: 10, Dst: 1, Type: 102, Time: 600757.6045
+Src: 15, Dst: 1, Type: 102, Time: 600757.6045
+Src: 28, Dst: 1, Type: 102, Time: 600757.6045
+Src: 12, Dst: 1, Type: 102, Time: 600757.6045
+Src: 39, Dst: 1, Type: 102, Time: 600757.6045
+Src: 136, Dst: , Type: 102, Time: 600757.6045
+Src: 31, Dst: , Type: 102, Time: 600757.6045
+Src: 2, Dst: 45, Type: 103, Time: 600757.4045
+Src: 2, Dst: 81, Type: 103, Time: 600757.4045
+Src: 2, Dst: 57, Type: 103, Time: 600757.4045
+Src: 2, Dst: 64, Type: 103, Time: 600757.4045
+Src: 2, Dst: 52, Type: 103, Time: 600757.4045
+Src: 2, Dst: 252, Type: 103, Time: 600757.4045
+Src: 2, Dst: 43, Type: 103, Time: 600757.4045
+Src: 45, Dst: 2, Type: 104, Time: 600757.5045
+Src: 81, Dst: 2, Type: 104, Time: 600757.5045
+Src: 57, Dst: 2, Type: 104, Time: 600757.5045
+Src: 64, Dst: 2, Type: 104, Time: 600757.5045
+Src: 52, Dst: 2, Type: 104, Time: 600757.5045
+Src: 252, Dst: 2, Type: 104, Time: 600757.5045
+Src: 43, Dst: 2, Type: 104, Time: 600757.5045
+Src: 2, Dst: 45, Type: 101, Time: 600757.6045
+Src: 2, Dst: 81, Type: 101, Time: 600757.6045
+Src: 2, Dst: 57, Type: 101, Time: 600757.6045
+Src: 2, Dst: 64, Type: 101, Time: 600757.6045
+Src: 2, Dst: 52, Type: 101, Time: 600757.6045
+Src: 2, Dst: 252, Type: 101, Time: 600757.6045
+Src: 2, Dst: 43, Type: 101, Time: 600757.6045
+Src: 45, Dst: 2, Type: 102, Time: 600757.7045
+Src: 81, Dst: 2, Type: 102, Time: 600757.7045
+Src: 57, Dst: 2, Type: 102, Time: 600757.7045
+Src: 64, Dst: 2, Type: 102, Time: 600757.7045
+Src: 52, Dst: 2, Type: 102, Time: 600757.7045
+Src: 252, Dst: 2, Type: 102, Time: 600757.7045
+Src: 43, Dst: 2, Type: 102, Time: 600757.7045
+Src: 3, Dst: 73, Type: 103, Time: 600757.4045
+Src: 3, Dst: 219, Type: 103, Time: 600757.4045
+Src: 3, Dst: 142, Type: 103, Time: 600757.4045
+Src: 3, Dst: 232, Type: 103, Time: 600757.4045
+Src: 3, Dst: 115, Type: 103, Time: 600757.4045
+Src: 3, Dst: 177, Type: 103, Time: 600757.4045
+Src: 3, Dst: 5, Type: 103, Time: 600757.4045
+Src: 73, Dst: 3, Type: 104, Time: 600757.5045
+Src: 219, Dst: 3, Type: 104, Time: 600757.5045
+Src: 142, Dst: 3, Type: 104, Time: 600757.5045
+Src: 232, Dst: 3, Type: 104, Time: 600757.5045
+Src: 115, Dst: 3, Type: 104, Time: 600757.5045
+Src: 94, Dst: 3, Type: 104, Time: 600757.5045
+Src: 177, Dst: 3, Type: 104, Time: 600757.5045
+Src: 3, Dst: 73, Type: 101, Time: 600757.6045
+Src: 3, Dst: 219, Type: 101, Time: 600757.6045
+Src: 3, Dst: 142, Type: 101, Time: 600757.6045
+Src: 3, Dst: 232, Type: 101, Time: 600757.6045
+Src: 3, Dst: 115, Type: 101, Time: 600757.6045
+Src: 3, Dst: 177, Type: 101, Time: 600757.6045
+Src: 3, Dst: 5, Type: 101, Time: 600757.6045
+Src: 73, Dst: 3, Type: 102, Time: 600757.7045
+Src: 219, Dst: 3, Type: 102, Time: 600757.7045
+Src: 142, Dst: 3, Type: 102, Time: 600757.7045
+Src: 232, Dst: 3, Type: 102, Time: 600757.7045
+Src: 115, Dst: 3, Type: 102, Time: 600757.7045
+Src: 94, Dst: 3, Type: 102, Time: 600757.7045
+Src: 177, Dst: 3, Type: 102, Time: 600757.7045
+Src: 10, Dst: 111, Type: 103, Time: 600757.5045
+Src: 10, Dst: 79, Type: 103, Time: 600757.5045
+Src: 111, Dst: 10, Type: 104, Time: 600757.6045
+Src: 79, Dst: 10, Type: 104, Time: 600757.6045
+Src: 10, Dst: 111, Type: 101, Time: 600757.7045
+Src: 10, Dst: 79, Type: 101, Time: 600757.7045
+Src: 111, Dst: 10, Type: 102, Time: 600757.8045
+Src: 79, Dst: 10, Type: 102, Time: 600757.8045
+Src: 15, Dst: 137, Type: 103, Time: 600757.5045
+Src: 15, Dst: 170, Type: 103, Time: 600757.5045
+Src: 137, Dst: 15, Type: 104, Time: 600757.6045
+Src: 170, Dst: 15, Type: 104, Time: 600757.6045
+Src: 15, Dst: 137, Type: 101, Time: 600757.7045
+Src: 15, Dst: 170, Type: 101, Time: 600757.7045
+Src: 137, Dst: 15, Type: 102, Time: 600757.8045
+Src: 170, Dst: 15, Type: 102, Time: 600757.8045
+Src: 28, Dst: 119, Type: 103, Time: 600757.6045
+Src: 28, Dst: 171, Type: 103, Time: 600757.6045
+Src: 119, Dst: 28, Type: 104, Time: 600757.7045
+Src: 171, Dst: 28, Type: 104, Time: 600757.7045
+Src: 28, Dst: 119, Type: 101, Time: 600757.8045
+Src: 28, Dst: 171, Type: 101, Time: 600757.8045
+Src: 119, Dst: 28, Type: 102, Time: 600757.9045
+Src: 171, Dst: 28, Type: 102, Time: 600757.9045
+Src: 12, Dst: 128, Type: 103, Time: 600757.6045
+Src: 12, Dst: 251, Type: 103, Time: 600757.6045
+Src: 128, Dst: 12, Type: 104, Time: 600757.7045
+Src: 251, Dst: 12, Type: 104, Time: 600757.7045
+Src: 12, Dst: 128, Type: 101, Time: 600757.8045
+Src: 12, Dst: 251, Type: 101, Time: 600757.8045
+Src: 128, Dst: 12, Type: 102, Time: 600757.9045
+Src: 251, Dst: 12, Type: 102, Time: 600757.9045
+Src: 39, Dst: 179, Type: 103, Time: 600757.7045
+Src: 39, Dst: 22, Type: 103, Time: 600757.7045
+Src: 179, Dst: 39, Type: 104, Time: 600757.8045
+Src: 22, Dst: 39, Type: 104, Time: 600757.8045
+Src: 39, Dst: 179, Type: 101, Time: 600757.9045
+Src: 39, Dst: 22, Type: 101, Time: 600757.9045
+Src: 179, Dst: 39, Type: 102, Time: 600758.0045
+Src: 22, Dst: 39, Type: 102, Time: 600758.0045
+Src: 45, Dst: 242, Type: 103, Time: 600757.7045
+Src: 45, Dst: 87, Type: 103, Time: 600757.7045
+Src: 242, Dst: 45, Type: 104, Time: 600757.8045
+Src: 87, Dst: 45, Type: 104, Time: 600757.8045
+Src: 45, Dst: 242, Type: 101, Time: 600757.9045
+Src: 45, Dst: 87, Type: 101, Time: 600757.9045
+Src: 242, Dst: 45, Type: 102, Time: 600758.0045
+Src: 87, Dst: 45, Type: 102, Time: 600758.0045
+Src: 81, Dst: 80, Type: 103, Time: 600757.7045
+Src: 81, Dst: 166, Type: 103, Time: 600757.7045
+Src: 80, Dst: 81, Type: 104, Time: 600757.8045
+Src: 166, Dst: 81, Type: 104, Time: 600757.8045
+Src: 81, Dst: 80, Type: 101, Time: 600757.9045
+Src: 81, Dst: 166, Type: 101, Time: 600757.9045
+Src: 80, Dst: 81, Type: 102, Time: 600758.0045
+Src: 166, Dst: 81, Type: 102, Time: 600758.0045
+Src: 57, Dst: 65, Type: 103, Time: 600757.7045
+Src: 57, Dst: 223, Type: 103, Time: 600757.7045
+Src: 65, Dst: 57, Type: 104, Time: 600757.8045
+Src: 223, Dst: 57, Type: 104, Time: 600757.8045
+Src: 57, Dst: 65, Type: 101, Time: 600757.9045
+Src: 57, Dst: 223, Type: 101, Time: 600757.9045
+Src: 65, Dst: 57, Type: 102, Time: 600758.0045
+Src: 223, Dst: 57, Type: 102, Time: 600758.0045
+Src: 64, Dst: 235, Type: 103, Time: 600757.6045
+Src: 64, Dst: 44, Type: 103, Time: 600757.6045
+Src: 235, Dst: 64, Type: 104, Time: 600757.7045
+Src: 44, Dst: 64, Type: 104, Time: 600757.7045
+Src: 64, Dst: 235, Type: 101, Time: 600757.8045
+Src: 64, Dst: 44, Type: 101, Time: 600757.8045
+Src: 235, Dst: 64, Type: 102, Time: 600757.9045
+Src: 44, Dst: 64, Type: 102, Time: 600757.9045
+Src: 52, Dst: 66, Type: 103, Time: 600757.6045
+Src: 52, Dst: 215, Type: 103, Time: 600757.6045
+Src: 66, Dst: 52, Type: 104, Time: 600757.7045
+Src: 215, Dst: 52, Type: 104, Time: 600757.7045
+Src: 52, Dst: 66, Type: 101, Time: 600757.8045
+Src: 52, Dst: 215, Type: 101, Time: 600757.8045
+Src: 66, Dst: 52, Type: 102, Time: 600757.9045
+Src: 215, Dst: 52, Type: 102, Time: 600757.9045
+Src: 73, Dst: 184, Type: 103, Time: 600757.9045
+Src: 73, Dst: 114, Type: 103, Time: 600757.9045
+Src: 184, Dst: 73, Type: 104, Time: 600758.0045
+Src: 114, Dst: 73, Type: 104, Time: 600758.0045
+Src: 73, Dst: 184, Type: 101, Time: 600757.1045
+Src: 73, Dst: 114, Type: 101, Time: 600757.1045
+Src: 184, Dst: 73, Type: 102, Time: 600758.2045
+Src: 114, Dst: 73, Type: 102, Time: 600758.2045
+Src: 219, Dst: 156, Type: 103, Time: 600757.9045
+Src: 219, Dst: 239, Type: 103, Time: 600757.9045
+Src: 156, Dst: 219, Type: 104, Time: 600758.0045
+Src: 239, Dst: 219, Type: 104, Time: 600758.0045
+Src: 219, Dst: 156, Type: 101, Time: 600758.1045
+Src: 219, Dst: 239, Type: 101, Time: 600758.1045
+Src: 156, Dst: 219, Type: 102, Time: 600758.2045
+Src: 239, Dst: 219, Type: 102, Time: 600758.2045
+Src: 142, Dst: 100, Type: 103, Time: 600757.9045
+Src: 142, Dst: 181, Type: 103, Time: 600757.9045
+Src: 100, Dst: 142, Type: 104, Time: 600758.0045
+Src: 181, Dst: 142, Type: 104, Time: 600758.0045
+Src: 142, Dst: 100, Type: 101, Time: 600758.0045
+Src: 142, Dst: 181, Type: 101, Time: 600758.0045
+Src: 100, Dst: 142, Type: 102, Time: 600758.1045
+Src: 181, Dst: 142, Type: 102, Time: 600758.1045
+Src: 232, Dst: 61, Type: 103, Time: 600758.0045
+Src: 232, Dst: 209, Type: 103, Time: 600758.0045
+Src: 61, Dst: 232, Type: 104, Time: 600758.1045
+Src: 209, Dst: 232, Type: 104, Time: 600758.1045
+Src: 232, Dst: 61, Type: 101, Time: 600758.2045
+Src: 232, Dst: 209, Type: 101, Time: 600758.2045
+Src: 61, Dst: 232, Type: 102, Time: 600758.3045
+Src: 209, Dst: 232, Type: 102, Time: 600758.3045
+Src: 115, Dst: 140, Type: 103, Time: 600758.0045
+Src: 115, Dst: 160, Type: 103, Time: 600758.0045
+Src: 140, Dst: 115, Type: 104, Time: 600758.1045
+Src: 160, Dst: 115, Type: 104, Time: 600758.1045
+Src: 115, Dst: 140, Type: 101, Time: 600758.2045
+Src: 115, Dst: 160, Type: 101, Time: 600758.2045
+Src: 140, Dst: 115, Type: 102, Time: 600758.3045
+Src: 160, Dst: 115, Type: 102, Time: 600758.3045

+ 664 - 0
resources/testcsv_comments.csv

@@ -0,0 +1,664 @@
+Source, Destination, Type, Time
+// 3 Bots initiate contact
+Src: 1, Des: 2, Type: 103, Time: 756.1045
+Src: 1, Des: 3, Type: 103, Time: 756.1045
+Src: 2, Des: 1, Type: 104, Time: 756.2045
+Src: 3, Des: 1, Type: 104, Time: 756.3045
+
+// 5 additional bots contacted by Bot 1
+Src: 1, Des: 10, Type: 103, Time: 756.4045
+Src: 1, Des: 15, Type: 103, Time: 756.4045
+Src: 1, Des: 28, Type: 103, Time: 756.4045
+Src: 1, Des: 12, Type: 103, Time: 756.4045
+Src: 1, Des: 39, Type: 103, Time: 756.4045
+Src: 1, Des: 159, Type: 103, Time: 756.4045 // will not reply
+
+// answers of additional bots for bot 1
+Src: 10, Des: 1, Type: 104, Time: 756.5045
+Src: 15, Des: 1, Type: 104, Time: 756.5045
+Src: 28, Des: 1, Type: 104, Time: 756.5045
+Src: 12, Des: 1, Type: 104, Time: 756.5045
+Src: 39, Des: 1, Type: 104, Time: 756.5045
+Src: 159, Des: 1, Type: 3, Time: 756.8045 // timeout
+
+// 5 additional bots contacted by Bot 2
+Src: 2, Des: 45, Type: 103, Time: 756.5045
+Src: 2, Des: 81, Type: 103, Time: 756.5045
+Src: 2, Des: 57, Type: 103, Time: 756.5045
+Src: 2, Des: 64, Type: 103, Time: 756.5045
+Src: 2, Des: 52, Type: 103, Time: 756.5045
+Src: 2, Des: 11, Type: 103, Time: 756.5045 // will not reply
+
+// answers of additional bots for bot 2
+Src: 45, Des: 2, Type: 104, Time: 756.6045
+Src: 81, Des: 2, Type: 104, Time: 756.6045
+Src: 57, Des: 2, Type: 104, Time: 756.6045
+Src: 64, Des: 2, Type: 104, Time: 756.6045
+Src: 52, Des: 2, Type: 104, Time: 756.6045
+Src: 11, Des: 2, Type: 3, Time: 756.9045 // timeout
+
+// 5 additional bots contacted by Bot 3
+Src: 3, Des: 73, Type: 103, Time: 756.6045
+Src: 3, Des: 219, Type: 103, Time: 756.6045
+Src: 3, Des: 142, Type: 103, Time: 756.6045
+Src: 3, Des: 232, Type: 103, Time: 756.6045
+Src: 3, Des: 115, Type: 103, Time: 756.6045
+Src: 3, Des: 94, Type: 103, Time: 756.6045 // will not reply
+
+// answers of additional bots for bot 3
+Src: 73, Des: 3, Type: 104, Time: 756.7045
+Src: 219, Des: 3, Type: 104, Time: 756.7045
+Src: 142, Des: 3, Type: 104, Time: 756.7045
+Src: 232, Des: 3, Type: 104, Time: 756.7045
+Src: 115, Des: 3, Type: 104, Time: 756.7045
+Src: 94, Des: 3, Type: 3, Time: 757.0045 // timeout
+
+// 2 additional external Bots contacted by all bots
+// and answers of the 2 additional external Bots
+Src: 1, Des: 136, Type: 103, Time: 756.7045
+Src: 136, Des: 1, Type: 104, Time: 756.8045
+
+Src: 1, Des: 31, Type: 103, Time: 756.7045
+Src: 31, Des: 1, Type: 104, Time: 756.8045
+
+Src: 2, Des: 252, Type: 103, Time: 756.7045
+Src: 252, Des: 2, Type: 104, Time: 756.8045
+
+Src: 2, Des: 43, Type: 103, Time: 756.7045
+Src: 43, Des: 2, Type: 104, Time: 756.8045
+
+Src: 3, Des: 177, Type: 103, Time: 756.7045
+Src: 177, Des: 3, Type: 104, Time: 756.8045
+
+Src: 3, Des: 5, Type: 103, Time: 756.7045
+Src: 5, Des: 3, Type: 104, Time: 756.8045
+
+Src: 10, Des: 111, Type: 103, Time: 756.8045
+Src: 111, Des: 10, Type: 104, Time: 756.9045
+
+Src: 10, Des: 79, Type: 103, Time: 756.8045
+Src: 79, Des: 10, Type: 104, Time: 756.9045
+
+Src: 15, Des: 137, Type: 103, Time: 756.8045
+Src: 137, Des: 15, Type: 104, Time: 756.9045
+
+Src: 15, Des: 170, Type: 103, Time: 756.8045
+Src: 170, Des: 15, Type: 104, Time: 756.9045
+
+Src: 28, Des: 119, Type: 103, Time: 756.9045
+Src: 119, Des: 28, Type: 104, Time: 757.0045
+
+Src: 28, Des: 171, Type: 103, Time: 756.9045
+Src: 171, Des: 28, Type: 104, Time: 757.0045
+
+Src: 12, Des: 128, Type: 103, Time: 756.9045
+Src: 128, Des: 12, Type: 104, Time: 757.0045
+
+Src: 12, Des: 251, Type: 103, Time: 756.9045
+Src: 251, Des: 12, Type: 104, Time: 757.0045
+
+Src: 39, Des: 179, Type: 103, Time: 757.0045
+Src: 179, Des: 39, Type: 104, Time: 757.1045
+
+Src: 39, Des: 22, Type: 103, Time: 757.0045
+Src: 22, Des: 39, Type: 104, Time: 757.1045
+
+Src: 45, Des: 242, Type: 103, Time: 757.0045
+Src: 242, Des: 45, Type: 104, Time: 757.1045
+
+Src: 45, Des: 87, Type: 103, Time: 757.0045
+Src: 87, Des: 45, Type: 104, Time: 757.1045
+
+Src: 81, Des: 80, Type: 103, Time: 757.1045
+Src: 80, Des: 81, Type: 104, Time: 757.2045
+
+Src: 81, Des: 166, Type: 103, Time: 757.1045
+Src: 166, Des: 81, Type: 104, Time: 757.2045
+
+Src: 57, Des: 65, Type: 103, Time: 757.1045
+Src: 65, Des: 57, Type: 104, Time: 757.2045
+
+Src: 57, Des: 223, Type: 103, Time: 757.1045
+Src: 223, Des: 57, Type: 104, Time: 757.2045
+
+Src: 64, Des: 235, Type: 103, Time: 757.1045
+Src: 235, Des: 64, Type: 104, Time: 757.2045
+
+Src: 64, Des: 44, Type: 103, Time: 757.1045
+Src: 44, Des: 64, Type: 104, Time: 757.2045
+
+Src: 52, Des: 66, Type: 103, Time: 757.1045
+Src: 66, Des: 52, Type: 104, Time: 757.2045
+
+Src: 52, Des: 215, Type: 103, Time: 757.1045
+Src: 215, Des: 52, Type: 104, Time: 757.2045
+
+Src: 73, Des: 184, Type: 103, Time: 757.1045
+Src: 184, Des: 73, Type: 104, Time: 757.2045
+
+Src: 73, Des: 114, Type: 103, Time: 757.1045
+Src: 114, Des: 73, Type: 104, Time: 757.2045
+
+Src: 219, Des: 156, Type: 103, Time: 757.1045
+Src: 156, Des: 219, Type: 104, Time: 757.2045
+
+Src: 219, Des: 239, Type: 103, Time: 757.1045
+Src: 239, Des: 219, Type: 104, Time: 757.2045
+
+Src: 142, Des: 100, Type: 103, Time: 757.1045
+Src: 100, Des: 142, Type: 104, Time: 757.2045
+
+Src: 142, Des: 181, Type: 103, Time: 757.1045
+Src: 181, Des: 142, Type: 104, Time: 757.2045
+
+Src: 232, Des: 61, Type: 103, Time: 757.1045
+Src: 61, Des: 232, Type: 104, Time: 757.2045
+
+Src: 232, Des: 209, Type: 103, Time: 757.1045
+Src: 209, Des: 232, Type: 104, Time: 757.2045
+
+Src: 115, Des: 140, Type: 103, Time: 757.2045
+Src: 140, Des: 115, Type: 104, Time: 757.3045
+
+Src: 115, Des: 160, Type: 103, Time: 757.2045
+Src: 160, Des: 115, Type: 104, Time: 757.3045
+
+// #############################################
+// First round start - only 103 + reply(104)
+// initiator #1
+Src: 1, Des: 2, Type: 103, Time: 757.3045
+Src: 1, Des: 3, Type: 103, Time: 757.3045
+Src: 1, Des: 10, Type: 103, Time: 757.3045
+Src: 1, Des: 15, Type: 103, Time: 757.3045
+Src: 1, Des: 28, Type: 103, Time: 757.3045
+Src: 1, Des: 12, Type: 103, Time: 757.3045
+Src: 1, Des: 39, Type: 103, Time: 757.3045
+Src: 1, Des: 136, Type: 103, Time: 757.3045
+Src: 1, Des: 31, Type: 103, Time: 757.3045
+
+// reply for initiator #1
+Src: 2, Des: 1, Type: 104, Time: 757.4045
+Src: 3, Des: 1, Type: 104, Time: 757.4045
+Src: 10, Des: 1, Type: 104, Time: 757.4045
+Src: 15, Des: 1, Type: 104, Time: 757.4045
+Src: 28, Des: 1, Type: 104, Time: 757.4045
+Src: 12, Des: 1, Type: 104, Time: 757.4045
+Src: 39, Des: 1, Type: 104, Time: 757.4045
+Src: 136, Des: , Type: 104, Time: 757.4045
+Src: 31, Des: , Type: 104, Time: 757.4045
+
+// initiator #2
+Src: 2, Des: 45, Type: 103, Time: 757.4045
+Src: 2, Des: 81, Type: 103, Time: 757.4045
+Src: 2, Des: 57, Type: 103, Time: 757.4045
+Src: 2, Des: 64, Type: 103, Time: 757.4045
+Src: 2, Des: 52, Type: 103, Time: 757.4045
+Src: 2, Des: 252, Type: 103, Time: 757.4045
+Src: 2, Des: 43, Type: 103, Time: 757.4045
+
+// reply for initiator #2
+Src: 45, Des: 2, Type: 104, Time: 757.5045
+Src: 81, Des: 2, Type: 104, Time: 757.5045
+Src: 57, Des: 2, Type: 104, Time: 757.5045
+Src: 64, Des: 2, Type: 104, Time: 757.5045
+Src: 52, Des: 2, Type: 104, Time: 757.5045
+Src: 252, Des: 2, Type: 104, Time: 757.5045
+Src: 43, Des: 2, Type: 104, Time: 757.5045
+
+// initiator #3 + reply
+Src: 3, Des: 73, Type: 103, Time: 757.4045
+Src: 3, Des: 219, Type: 103, Time: 757.4045
+Src: 3, Des: 142, Type: 103, Time: 757.4045
+Src: 3, Des: 232, Type: 103, Time: 757.4045
+Src: 3, Des: 115, Type: 103, Time: 757.4045
+Src: 3, Des: 177, Type: 103, Time: 757.4045
+Src: 3, Des: 5, Type: 103, Time: 757.4045
+
+// reply for initiator #3
+Src: 73, Des: 3, Type: 104, Time: 757.5045
+Src: 219, Des: 3, Type: 104, Time: 757.5045
+Src: 142, Des: 3, Type: 104, Time: 757.5045
+Src: 232, Des: 3, Type: 104, Time: 757.5045
+Src: 115, Des: 3, Type: 104, Time: 757.5045
+Src: 94, Des: 3, Type: 104, Time: 757.5045
+Src: 177, Des: 3, Type: 104, Time: 757.5045
+
+// initiator #10 + reply
+Src: 10, Des: 111, Type: 103, Time: 757.5045
+Src: 10, Des: 79, Type: 103, Time: 757.5045
+
+Src: 111, Des: 10, Type: 104, Time: 757.6045
+Src: 79, Des: 10, Type: 104, Time: 757.6045
+
+// initiator #15 + reply
+Src: 15, Des: 137, Type: 103, Time: 757.5045
+Src: 15, Des: 170, Type: 103, Time: 757.5045
+
+Src: 137, Des: 15, Type: 104, Time: 757.6045
+Src: 170, Des: 15, Type: 104, Time: 757.6045
+
+// initiator #28 + reply
+Src: 28, Des: 119, Type: 103, Time: 757.6045
+Src: 28, Des: 171, Type: 103, Time: 757.6045
+
+Src: 119, Des: 28, Type: 104, Time: 757.7045
+Src: 171, Des: 28, Type: 104, Time: 757.7045
+
+// initiator #12 + reply
+Src: 12, Des: 128, Type: 103, Time: 757.6045
+Src: 12, Des: 251, Type: 103, Time: 757.6045
+
+Src: 128, Des: 12, Type: 104, Time: 757.7045
+Src: 251, Des: 12, Type: 104, Time: 757.7045
+
+// initiator #39 + reply
+Src: 39, Des: 179, Type: 103, Time: 757.7045
+Src: 39, Des: 22, Type: 103, Time: 757.7045
+
+Src: 179, Des: 39, Type: 104, Time: 757.8045
+Src: 22, Des: 39, Type: 104, Time: 757.8045
+
+// initiator #45 + reply
+Src: 45, Des: 242, Type: 103, Time: 757.7045
+Src: 45, Des: 87, Type: 103, Time: 757.7045
+
+Src: 242, Des: 45, Type: 104, Time: 757.8045
+Src: 87, Des: 45, Type: 104, Time: 757.8045
+
+// initiator #81 + reply
+Src: 81, Des: 80, Type: 103, Time: 757.7045
+Src: 81, Des: 166, Type: 103, Time: 757.7045
+
+Src: 80, Des: 81, Type: 104, Time: 757.8045
+Src: 166, Des: 81, Type: 104, Time: 757.8045
+
+// initiator #57 + reply
+Src: 57, Des: 65, Type: 103, Time: 757.7045
+Src: 57, Des: 223, Type: 103, Time: 757.7045
+
+Src: 65, Des: 57, Type: 104, Time: 757.8045
+Src: 223, Des: 57, Type: 104, Time: 757.8045
+
+// initiator #64 + reply
+Src: 64, Des: 235, Type: 103, Time: 757.6045
+Src: 64, Des: 44, Type: 103, Time: 757.6045
+
+Src: 235, Des: 64, Type: 104, Time: 757.7045
+Src: 44, Des: 64, Type: 104, Time: 757.7045
+
+// initiator #52 + reply
+Src: 52, Des: 66, Type: 103, Time: 757.6045
+Src: 52, Des: 215, Type: 103, Time: 757.6045
+
+Src: 66, Des: 52, Type: 104, Time: 757.7045
+Src: 215, Des: 52, Type: 104, Time: 757.7045
+
+// initiator #73 + reply
+Src: 73, Des: 184, Type: 103, Time: 757.9045
+Src: 73, Des: 114, Type: 103, Time: 757.9045
+
+Src: 184, Des: 73, Type: 104, Time: 758.0045
+Src: 114, Des: 73, Type: 104, Time: 758.0045
+
+// initiator #219 + reply
+Src: 219, Des: 156, Type: 103, Time: 757.9045
+Src: 219, Des: 239, Type: 103, Time: 757.9045
+
+Src: 156, Des: 219, Type: 104, Time: 758.0045
+Src: 239, Des: 219, Type: 104, Time: 758.0045
+
+// initiator #142 + reply
+Src: 142, Des: 100, Type: 103, Time: 757.9045
+Src: 142, Des: 181, Type: 103, Time: 757.9045
+
+Src: 100, Des: 142, Type: 104, Time: 758.0045
+Src: 181, Des: 142, Type: 104, Time: 758.0045
+
+// initiator #232 + reply
+Src: 232, Des: 61, Type: 103, Time: 758.0045
+Src: 232, Des: 209, Type: 103, Time: 758.0045
+
+Src: 61, Des: 232, Type: 104, Time: 758.1045
+Src: 209, Des: 232, Type: 104, Time: 758.1045
+
+// initiator #115 + reply
+Src: 115, Des: 140, Type: 103, Time: 758.0045
+Src: 115, Des: 160, Type: 103, Time: 758.0045
+
+Src: 140, Des: 115, Type: 104, Time: 758.1045
+Src: 160, Des: 115, Type: 104, Time: 758.1045
+
+// ############################################
+// first round end
+// now wait 10min
+
+// #############################################
+// Second round start - only 103 + reply(104) followed by 101+reply(102)
+// initiator #1
+Src: 1, Des: 2, Type: 103, Time: 600757.3045
+Src: 1, Des: 3, Type: 103, Time: 600757.3045
+Src: 1, Des: 10, Type: 103, Time: 600757.3045
+Src: 1, Des: 15, Type: 103, Time: 600757.3045
+Src: 1, Des: 28, Type: 103, Time: 600757.3045
+Src: 1, Des: 12, Type: 103, Time: 600757.3045
+Src: 1, Des: 39, Type: 103, Time: 600757.3045
+Src: 1, Des: 136, Type: 103, Time: 600757.3045
+Src: 1, Des: 31, Type: 103, Time: 600757.3045
+
+// reply for initiator #1
+Src: 2, Des: 1, Type: 104, Time: 600757.4045
+Src: 3, Des: 1, Type: 104, Time: 600757.4045
+Src: 10, Des: 1, Type: 104, Time: 600757.4045
+Src: 15, Des: 1, Type: 104, Time: 600757.4045
+Src: 28, Des: 1, Type: 104, Time: 600757.4045
+Src: 12, Des: 1, Type: 104, Time: 600757.4045
+Src: 39, Des: 1, Type: 104, Time: 600757.4045
+Src: 136, Des: , Type: 104, Time: 600757.4045
+Src: 31, Des: , Type: 104, Time: 600757.4045
+
+// initiator #1 101
+Src: 1, Des: 2, Type: 101, Time: 600757.5045
+Src: 1, Des: 3, Type: 101, Time: 600757.5045
+Src: 1, Des: 10, Type: 101, Time: 600757.5045
+Src: 1, Des: 15, Type: 101, Time: 600757.5045
+Src: 1, Des: 28, Type: 101, Time: 600757.5045
+Src: 1, Des: 12, Type: 101, Time: 600757.5045
+Src: 1, Des: 39, Type: 101, Time: 600757.5045
+Src: 1, Des: 136, Type: 101, Time: 600757.5045
+Src: 1, Des: 31, Type: 101, Time: 600757.5045
+
+// reply 102 for initiator #1
+Src: 2, Des: 1, Type: 102, Time: 600757.6045
+Src: 3, Des: 1, Type: 102, Time: 600757.6045
+Src: 10, Des: 1, Type: 102, Time: 600757.6045
+Src: 15, Des: 1, Type: 102, Time: 600757.6045
+Src: 28, Des: 1, Type: 102, Time: 600757.6045
+Src: 12, Des: 1, Type: 102, Time: 600757.6045
+Src: 39, Des: 1, Type: 102, Time: 600757.6045
+Src: 136, Des: , Type: 102, Time: 600757.6045
+Src: 31, Des: , Type: 102, Time: 600757.6045
+
+// initiator #2
+Src: 2, Des: 45, Type: 103, Time: 600757.4045
+Src: 2, Des: 81, Type: 103, Time: 600757.4045
+Src: 2, Des: 57, Type: 103, Time: 600757.4045
+Src: 2, Des: 64, Type: 103, Time: 600757.4045
+Src: 2, Des: 52, Type: 103, Time: 600757.4045
+Src: 2, Des: 252, Type: 103, Time: 600757.4045
+Src: 2, Des: 43, Type: 103, Time: 600757.4045
+
+// reply for initiator #2
+Src: 45, Des: 2, Type: 104, Time: 600757.5045
+Src: 81, Des: 2, Type: 104, Time: 600757.5045
+Src: 57, Des: 2, Type: 104, Time: 600757.5045
+Src: 64, Des: 2, Type: 104, Time: 600757.5045
+Src: 52, Des: 2, Type: 104, Time: 600757.5045
+Src: 252, Des: 2, Type: 104, Time: 600757.5045
+Src: 43, Des: 2, Type: 104, Time: 600757.5045
+
+// initiator #2
+Src: 2, Des: 45, Type: 101, Time: 600757.6045
+Src: 2, Des: 81, Type: 101, Time: 600757.6045
+Src: 2, Des: 57, Type: 101, Time: 600757.6045
+Src: 2, Des: 64, Type: 101, Time: 600757.6045
+Src: 2, Des: 52, Type: 101, Time: 600757.6045
+Src: 2, Des: 252, Type: 101, Time: 600757.6045
+Src: 2, Des: 43, Type: 101, Time: 600757.6045
+
+// reply for initiator #2
+Src: 45, Des: 2, Type: 102, Time: 600757.7045
+Src: 81, Des: 2, Type: 102, Time: 600757.7045
+Src: 57, Des: 2, Type: 102, Time: 600757.7045
+Src: 64, Des: 2, Type: 102, Time: 600757.7045
+Src: 52, Des: 2, Type: 102, Time: 600757.7045
+Src: 252, Des: 2, Type: 102, Time: 600757.7045
+Src: 43, Des: 2, Type: 102, Time: 600757.7045
+
+// initiator #3 + reply
+Src: 3, Des: 73, Type: 103, Time: 600757.4045
+Src: 3, Des: 219, Type: 103, Time: 600757.4045
+Src: 3, Des: 142, Type: 103, Time: 600757.4045
+Src: 3, Des: 232, Type: 103, Time: 600757.4045
+Src: 3, Des: 115, Type: 103, Time: 600757.4045
+Src: 3, Des: 177, Type: 103, Time: 600757.4045
+Src: 3, Des: 5, Type: 103, Time: 600757.4045
+
+// reply for initiator #3
+Src: 73, Des: 3, Type: 104, Time: 600757.5045
+Src: 219, Des: 3, Type: 104, Time: 600757.5045
+Src: 142, Des: 3, Type: 104, Time: 600757.5045
+Src: 232, Des: 3, Type: 104, Time: 600757.5045
+Src: 115, Des: 3, Type: 104, Time: 600757.5045
+Src: 94, Des: 3, Type: 104, Time: 600757.5045
+Src: 177, Des: 3, Type: 104, Time: 600757.5045
+
+// initiator #3 101
+Src: 3, Des: 73, Type: 101, Time: 600757.6045
+Src: 3, Des: 219, Type: 101, Time: 600757.6045
+Src: 3, Des: 142, Type: 101, Time: 600757.6045
+Src: 3, Des: 232, Type: 101, Time: 600757.6045
+Src: 3, Des: 115, Type: 101, Time: 600757.6045
+Src: 3, Des: 177, Type: 101, Time: 600757.6045
+Src: 3, Des: 5, Type: 101, Time: 600757.6045
+
+// reply 102 for initiator #3
+Src: 73, Des: 3, Type: 102, Time: 600757.7045
+Src: 219, Des: 3, Type: 102, Time: 600757.7045
+Src: 142, Des: 3, Type: 102, Time: 600757.7045
+Src: 232, Des: 3, Type: 102, Time: 600757.7045
+Src: 115, Des: 3, Type: 102, Time: 600757.7045
+Src: 94, Des: 3, Type: 102, Time: 600757.7045
+Src: 177, Des: 3, Type: 102, Time: 600757.7045
+
+// initiator #10 + reply
+Src: 10, Des: 111, Type: 103, Time: 600757.5045
+Src: 10, Des: 79, Type: 103, Time: 600757.5045
+
+Src: 111, Des: 10, Type: 104, Time: 600757.6045
+Src: 79, Des: 10, Type: 104, Time: 600757.6045
+
+// initiator #10 + reply
+Src: 10, Des: 111, Type: 101, Time: 600757.7045
+Src: 10, Des: 79, Type: 101, Time: 600757.7045
+
+Src: 111, Des: 10, Type: 102, Time: 600757.8045
+Src: 79, Des: 10, Type: 102, Time: 600757.8045
+
+// initiator #15 + reply
+Src: 15, Des: 137, Type: 103, Time: 600757.5045
+Src: 15, Des: 170, Type: 103, Time: 600757.5045
+
+Src: 137, Des: 15, Type: 104, Time: 600757.6045
+Src: 170, Des: 15, Type: 104, Time: 600757.6045
+
+// initiator #15 + reply
+Src: 15, Des: 137, Type: 101, Time: 600757.7045
+Src: 15, Des: 170, Type: 101, Time: 600757.7045
+
+Src: 137, Des: 15, Type: 102, Time: 600757.8045
+Src: 170, Des: 15, Type: 102, Time: 600757.8045
+
+// initiator #28 + reply
+Src: 28, Des: 119, Type: 103, Time: 600757.6045
+Src: 28, Des: 171, Type: 103, Time: 600757.6045
+
+Src: 119, Des: 28, Type: 104, Time: 600757.7045
+Src: 171, Des: 28, Type: 104, Time: 600757.7045
+
+// initiator #28 + reply
+Src: 28, Des: 119, Type: 101, Time: 600757.8045
+Src: 28, Des: 171, Type: 101, Time: 600757.8045
+
+Src: 119, Des: 28, Type: 102, Time: 600757.9045
+Src: 171, Des: 28, Type: 102, Time: 600757.9045
+
+// initiator #12 + reply
+Src: 12, Des: 128, Type: 103, Time: 600757.6045
+Src: 12, Des: 251, Type: 103, Time: 600757.6045
+
+Src: 128, Des: 12, Type: 104, Time: 600757.7045
+Src: 251, Des: 12, Type: 104, Time: 600757.7045
+
+// initiator #12 + reply
+Src: 12, Des: 128, Type: 101, Time: 600757.8045
+Src: 12, Des: 251, Type: 101, Time: 600757.8045
+
+Src: 128, Des: 12, Type: 102, Time: 600757.9045
+Src: 251, Des: 12, Type: 102, Time: 600757.9045
+
+// initiator #39 + reply
+Src: 39, Des: 179, Type: 103, Time: 600757.7045
+Src: 39, Des: 22, Type: 103, Time: 600757.7045
+
+Src: 179, Des: 39, Type: 104, Time: 600757.8045
+Src: 22, Des: 39, Type: 104, Time: 600757.8045
+
+// initiator #39 + reply
+Src: 39, Des: 179, Type: 101, Time: 600757.9045
+Src: 39, Des: 22, Type: 101, Time: 600757.9045
+
+Src: 179, Des: 39, Type: 102, Time: 600758.0045
+Src: 22, Des: 39, Type: 102, Time: 600758.0045
+
+// initiator #45 + reply
+Src: 45, Des: 242, Type: 103, Time: 600757.7045
+Src: 45, Des: 87, Type: 103, Time: 600757.7045
+
+Src: 242, Des: 45, Type: 104, Time: 600757.8045
+Src: 87, Des: 45, Type: 104, Time: 600757.8045
+
+// initiator #45 + reply
+Src: 45, Des: 242, Type: 101, Time: 600757.9045
+Src: 45, Des: 87, Type: 101, Time: 600757.9045
+
+Src: 242, Des: 45, Type: 102, Time: 600758.0045
+Src: 87, Des: 45, Type: 102, Time: 600758.0045
+
+// initiator #81 + reply
+Src: 81, Des: 80, Type: 103, Time: 600757.7045
+Src: 81, Des: 166, Type: 103, Time: 600757.7045
+
+Src: 80, Des: 81, Type: 104, Time: 600757.8045
+Src: 166, Des: 81, Type: 104, Time: 600757.8045
+
+// initiator #81 + reply
+Src: 81, Des: 80, Type: 101, Time: 600757.9045
+Src: 81, Des: 166, Type: 101, Time: 600757.9045
+
+Src: 80, Des: 81, Type: 102, Time: 600758.0045
+Src: 166, Des: 81, Type: 102, Time: 600758.0045
+
+// initiator #57 + reply
+Src: 57, Des: 65, Type: 103, Time: 600757.7045
+Src: 57, Des: 223, Type: 103, Time: 600757.7045
+
+Src: 65, Des: 57, Type: 104, Time: 600757.8045
+Src: 223, Des: 57, Type: 104, Time: 600757.8045
+
+// initiator #57 + reply
+Src: 57, Des: 65, Type: 101, Time: 600757.9045
+Src: 57, Des: 223, Type: 101, Time: 600757.9045
+
+Src: 65, Des: 57, Type: 102, Time: 600758.0045
+Src: 223, Des: 57, Type: 102, Time: 600758.0045
+
+// initiator #64 + reply
+Src: 64, Des: 235, Type: 103, Time: 600757.6045
+Src: 64, Des: 44, Type: 103, Time: 600757.6045
+
+Src: 235, Des: 64, Type: 104, Time: 600757.7045
+Src: 44, Des: 64, Type: 104, Time: 600757.7045
+
+// initiator #64 + reply
+Src: 64, Des: 235, Type: 101, Time: 600757.8045
+Src: 64, Des: 44, Type: 101, Time: 600757.8045
+
+Src: 235, Des: 64, Type: 102, Time: 600757.9045
+Src: 44, Des: 64, Type: 102, Time: 600757.9045
+
+// initiator #52 + reply
+Src: 52, Des: 66, Type: 103, Time: 600757.6045
+Src: 52, Des: 215, Type: 103, Time: 600757.6045
+
+Src: 66, Des: 52, Type: 104, Time: 600757.7045
+Src: 215, Des: 52, Type: 104, Time: 600757.7045
+
+// initiator #52 + reply
+Src: 52, Des: 66, Type: 101, Time: 600757.8045
+Src: 52, Des: 215, Type: 101, Time: 600757.8045
+
+Src: 66, Des: 52, Type: 102, Time: 600757.9045
+Src: 215, Des: 52, Type: 102, Time: 600757.9045
+
+// initiator #73 + reply
+Src: 73, Des: 184, Type: 103, Time: 600757.9045
+Src: 73, Des: 114, Type: 103, Time: 600757.9045
+
+Src: 184, Des: 73, Type: 104, Time: 600758.0045
+Src: 114, Des: 73, Type: 104, Time: 600758.0045
+
+// initiator #73 + reply
+Src: 73, Des: 184, Type: 101, Time: 600757.1045
+Src: 73, Des: 114, Type: 101, Time: 600757.1045
+
+Src: 184, Des: 73, Type: 102, Time: 600758.2045
+Src: 114, Des: 73, Type: 102, Time: 600758.2045
+
+// initiator #219 + reply
+Src: 219, Des: 156, Type: 103, Time: 600757.9045
+Src: 219, Des: 239, Type: 103, Time: 600757.9045
+
+Src: 156, Des: 219, Type: 104, Time: 600758.0045
+Src: 239, Des: 219, Type: 104, Time: 600758.0045
+
+// initiator #219 + reply
+Src: 219, Des: 156, Type: 101, Time: 600758.1045
+Src: 219, Des: 239, Type: 101, Time: 600758.1045
+
+Src: 156, Des: 219, Type: 102, Time: 600758.2045
+Src: 239, Des: 219, Type: 102, Time: 600758.2045
+
+// initiator #142 + reply
+Src: 142, Des: 100, Type: 103, Time: 600757.9045
+Src: 142, Des: 181, Type: 103, Time: 600757.9045
+
+Src: 100, Des: 142, Type: 104, Time: 600758.0045
+Src: 181, Des: 142, Type: 104, Time: 600758.0045
+
+// initiator #142 + reply
+Src: 142, Des: 100, Type: 101, Time: 600758.0045
+Src: 142, Des: 181, Type: 101, Time: 600758.0045
+
+Src: 100, Des: 142, Type: 102, Time: 600758.1045
+Src: 181, Des: 142, Type: 102, Time: 600758.1045
+
+// initiator #232 + reply
+Src: 232, Des: 61, Type: 103, Time: 600758.0045
+Src: 232, Des: 209, Type: 103, Time: 600758.0045
+
+Src: 61, Des: 232, Type: 104, Time: 600758.1045
+Src: 209, Des: 232, Type: 104, Time: 600758.1045
+
+// initiator #232 + reply
+Src: 232, Des: 61, Type: 101, Time: 600758.2045
+Src: 232, Des: 209, Type: 101, Time: 600758.2045
+
+Src: 61, Des: 232, Type: 102, Time: 600758.3045
+Src: 209, Des: 232, Type: 102, Time: 600758.3045
+
+// initiator #115 + reply
+Src: 115, Des: 140, Type: 103, Time: 600758.0045
+Src: 115, Des: 160, Type: 103, Time: 600758.0045
+
+Src: 140, Des: 115, Type: 104, Time: 600758.1045
+Src: 160, Des: 115, Type: 104, Time: 600758.1045
+
+// initiator #115 + reply
+Src: 115, Des: 140, Type: 101, Time: 600758.2045
+Src: 115, Des: 160, Type: 101, Time: 600758.2045
+
+Src: 140, Des: 115, Type: 102, Time: 600758.3045
+Src: 160, Des: 115, Type: 102, Time: 600758.3045
+
+// ############################################
+// second round end

+ 37 - 4
test/test_pcap_comparator.py

@@ -20,6 +20,17 @@ class PcapComparison(unittest.TestCase):
 
 
     OUTPUT_FILES_PREFIX_LINE = "Output files created:"
     OUTPUT_FILES_PREFIX_LINE = "Output files created:"
 
 
+    def __init__(self, *args, **kwargs):
+        unittest.TestCase.__init__(self, *args, **kwargs)
+
+        # params to call id2t with, as a list[list[str]]
+        # do a round of testing for each list[str] we get
+        # if none generate some params itself
+        self.id2t_params = None
+
+    def set_id2t_params(self, params: "list[list[str]]"):
+        self.id2t_params = params
+
     def setUp(self):
     def setUp(self):
         self.generated_files = []
         self.generated_files = []
         self.keep_files = []
         self.keep_files = []
@@ -28,7 +39,14 @@ class PcapComparison(unittest.TestCase):
         input_pcap = os.environ.get(self.PCAP_ENVIRONMENT_VALUE, self.DEFAULT_PCAP)
         input_pcap = os.environ.get(self.PCAP_ENVIRONMENT_VALUE, self.DEFAULT_PCAP)
         seed = os.environ.get(self.SEED_ENVIRONMENT_VALUE, self.DEFAULT_SEED)
         seed = os.environ.get(self.SEED_ENVIRONMENT_VALUE, self.DEFAULT_SEED)
 
 
-        command_args = [self.ID2T_LOCATION, "-i", input_pcap, "--seed", seed, "-a", "MembersMgmtCommAttack"]
+        if self.id2t_params is None:
+            self.id2t_params = self.random_id2t_params()
+
+        for params in self.id2t_params:
+            self.do_test_round(input_pcap, seed, params)
+
+    def do_test_round(self, input_pcap, seed, additional_params):
+        command_args = [self.ID2T_LOCATION, "-i", input_pcap, "--seed", seed, "-a", "MembersMgmtCommAttack"] + additional_params
         command = " ".join(map(shlex.quote, command_args))
         command = " ".join(map(shlex.quote, command_args))
         self.print_warning("The command that gets executed is:", command)
         self.print_warning("The command that gets executed is:", command)
 
 
@@ -44,7 +62,8 @@ class PcapComparison(unittest.TestCase):
 
 
             pcap = self.find_pcap(files)
             pcap = self.find_pcap(files)
             if generated_pcap is not None:
             if generated_pcap is not None:
-                try: self.compare_pcaps(generated_pcap, pcap)
+                try:
+                    self.compare_pcaps(generated_pcap, pcap)
                 except AssertionError as e:
                 except AssertionError as e:
                     self.keep_files = [generated_pcap, pcap]
                     self.keep_files = [generated_pcap, pcap]
                     raise e
                     raise e
@@ -52,7 +71,7 @@ class PcapComparison(unittest.TestCase):
                 generated_pcap = pcap
                 generated_pcap = pcap
 
 
             self.print_warning()
             self.print_warning()
-            time.sleep(1) # let some time pass between calls because files are based on the time
+            time.sleep(1)  # let some time pass between calls because files are based on the time
 
 
     def tearDown(self):
     def tearDown(self):
         self.print_warning("Cleaning up files generated by the test-calls...")
         self.print_warning("Cleaning up files generated by the test-calls...")
@@ -109,8 +128,22 @@ class PcapComparison(unittest.TestCase):
     def print_warning(self, *text):
     def print_warning(self, *text):
         print(*text, file=sys.stderr)
         print(*text, file=sys.stderr)
 
 
+    def random_id2t_params(self):
+        param = lambda key, val: "-p%s=%s" % (str(key), str(val))
+
+        return [
+            []
+        ]
+
 if __name__ == "__main__":
 if __name__ == "__main__":
+    import sys
+
+    # parameters for this program are interpreted as id2t-parameters
+    id2t_args = sys.argv[1:]
+    comparison = PcapComparison("test_determinism")
+    if id2t_args: comparison.set_id2t_params([id2t_args])
+
     suite = unittest.TestSuite()
     suite = unittest.TestSuite()
-    suite.addTest(PcapComparison("test_determinism"))
+    suite.addTest(comparison)
 
 
     unittest.TextTestRunner().run(suite)
     unittest.TextTestRunner().run(suite)