소스 검색

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

dustin.born 7 년 전
부모
커밋
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
     # recommended type: Positive Integer between 0 and 100 ------------------------------------
     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):
     """

+ 47 - 27
code/Attack/MembersMgmtCommAttack.py

@@ -109,7 +109,8 @@ class MembersMgmtCommAttack(BaseAttack.BaseAttack):
             Param.NAT_PRESENT: ParameterTypes.TYPE_BOOLEAN,
 
             # 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
@@ -154,6 +155,7 @@ class MembersMgmtCommAttack(BaseAttack.BaseAttack):
 
         # 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.BOTNET_DST_PORT_CALCULATION, True)
 
 
     def generate_attack_pcap(self, context):
@@ -178,6 +180,7 @@ class MembersMgmtCommAttack(BaseAttack.BaseAttack):
         limit_packetcount = self.get_param_value(Param.PACKETS_LIMIT)
         limit_duration = self.get_param_value(Param.ATTACK_DURATION)
         path_attack_pcap = None
+        overThousand = False
 
         msg_packet_mapping = MessageMapping(messages)
 
@@ -220,18 +223,33 @@ class MembersMgmtCommAttack(BaseAttack.BaseAttack):
             if total_pkts <= 1:
                 self.attack_start_utime = packets[0].time
             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 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
         msg_packet_mapping.write_to(context.allocate_file("_mapping.xml"))
@@ -293,12 +311,11 @@ class MembersMgmtCommAttack(BaseAttack.BaseAttack):
             else:
                 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
             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())
             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):
             """
             Assigns realistic timestamps to a set of messages
-            
+
             :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 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
                                     # 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
-                last_response[(msg.src, msg.dst)] = -1  
+                last_response[(msg.src, msg.dst)] = -1
 
             # update all timestamps
             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:
                         #external communication
                         respns_msg.time = req_msg.time + avg_delay_external + uniform(-0.1*avg_delay_external, 0.1*avg_delay_external)
-                    
+
                     else:
                         #local communication
                         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:
                     # every line consists of: IP, TTL, Frequency
                     next(file)  # skip CSV header line
-                    for line in file: 
+                    for line in file:
                         ip_addr, ttl, freq = line.split(",")
                         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][ttl] = int(freq)
-                        
+
                 return ip_based_distrib
 
             def get_total_ttl_distrib():
@@ -402,12 +419,12 @@ class MembersMgmtCommAttack(BaseAttack.BaseAttack):
                 with open("resources/CaidaTTL_total.csv", "r") as file:
                     # every line consists of: TTL, Frequency, Fraction
                     next(file)  # skip CSV header line
-                    for line in file: 
+                    for line in file:
                         ttl, freq, _ = line.split(",")
                         total_ttl_distrib[ttl] = int(freq)
-                        
+
                 return total_ttl_distrib
-            
+
             # get the TTL distribution for every IP that is available in "resources/CaidaTTL_perIP.csv"
             ip_ttl_distrib = get_ip_ttl_distrib()
             # build a probability dict for the total TTL distribution
@@ -422,7 +439,7 @@ class MembersMgmtCommAttack(BaseAttack.BaseAttack):
                     bot_configs[bot_id]["TTL"] = 128
 
                 # 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]
                     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()
@@ -519,6 +536,8 @@ class MembersMgmtCommAttack(BaseAttack.BaseAttack):
             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))
             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)])
             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
         # 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]["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
         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",
                                  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
         parser.add_argument('-a', '--attack', metavar="ATTACK", action='append',
                                        help='injects ATTACK into a PCAP file.', nargs='+')
@@ -162,7 +165,12 @@ class CLI(object):
         # Process attack(s) with given attack params
         if self.args.attack is not None:
             # 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
         if self.args.query == [None]:
@@ -184,3 +192,4 @@ def main(args):
 # Uncomment to enable calling by terminal
 if __name__ == '__main__':
     main(sys.argv[1:])
+

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

@@ -1,5 +1,6 @@
 import os.path
 from xml.dom.minidom import *
+import datetime
 
 
 class MessageMapping:
@@ -33,7 +34,11 @@ class MessageMapping:
             mapping.setAttribute("Src", str(message.src["ID"]))
             mapping.setAttribute("Dst", str(message.dst["ID"]))
             mapping.setAttribute("Type", str(message.type.value))
+
+            dt = datetime.datetime.fromtimestamp(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)
             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
         # keep track of previous request to find connections
         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
         external_init_ids = set()
 
@@ -154,9 +157,10 @@ class CommunicationProcessor():
                 msgs.append(msg)
                 prev_reqs[msg_str] = msg_id
                 msg_id += 1
+                req_seen = True
 
             # 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:
                     # process ID's role
                     external_init_ids.add(id_dst)

+ 20 - 7
code/ID2TLib/Controller.py

@@ -1,6 +1,7 @@
 import os
 import sys
 import shutil
+import time
 
 from ID2TLib.AttackController import AttackController
 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)
 
-    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
         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"]].
         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 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
@@ -85,12 +87,23 @@ class Controller:
         else:
             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 not self.pcap_out_path.endswith(".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
 	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
 	: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):
 	'''
 	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
 	: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
 '''
 
-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 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
     '''
 
-    if(user_padding and bytes_padding > 100):
+    if(user_padding == True and bytes_padding > 100):
         bytes_padding = 100
 
     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
     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 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:
         bytes_padding = largest_packet - len(packet)
         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
 
@@ -390,4 +395,4 @@ class MappingIPGenerator(IPGenerator):
         return self.mapping[key]
 
     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
 
+    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):
         """
         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]))
                     done.append(p1)
                     done.append(p2)
-                    # print("duplicate found:", p1, " and ", p2)
                     added = True
                     break
 
@@ -1143,6 +1182,61 @@ class Statistics:
             else:
                 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):
             """
             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_out_degree = plot_out_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_time_between_comm_interval_out = plot_avg_time_between_comm_interval('.' + 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:"
 
+    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):
         self.generated_files = []
         self.keep_files = []
@@ -28,7 +39,14 @@ class PcapComparison(unittest.TestCase):
         input_pcap = os.environ.get(self.PCAP_ENVIRONMENT_VALUE, self.DEFAULT_PCAP)
         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))
         self.print_warning("The command that gets executed is:", command)
 
@@ -44,7 +62,8 @@ class PcapComparison(unittest.TestCase):
 
             pcap = self.find_pcap(files)
             if generated_pcap is not None:
-                try: self.compare_pcaps(generated_pcap, pcap)
+                try:
+                    self.compare_pcaps(generated_pcap, pcap)
                 except AssertionError as e:
                     self.keep_files = [generated_pcap, pcap]
                     raise e
@@ -52,7 +71,7 @@ class PcapComparison(unittest.TestCase):
                 generated_pcap = pcap
 
             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):
         self.print_warning("Cleaning up files generated by the test-calls...")
@@ -109,8 +128,22 @@ class PcapComparison(unittest.TestCase):
     def print_warning(self, *text):
         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__":
+    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.addTest(PcapComparison("test_determinism"))
+    suite.addTest(comparison)
 
     unittest.TextTestRunner().run(suite)