Browse Source

Use the simple approach for interval selection in all cases.

dustin.born 6 years ago
parent
commit
cdd5874748
2 changed files with 14 additions and 146 deletions
  1. 2 1
      code/Attack/MembersMgmtCommAttack.py
  2. 12 145
      code/ID2TLib/CommunicationProcessor.py

+ 2 - 1
code/Attack/MembersMgmtCommAttack.py

@@ -357,6 +357,7 @@ class MembersMgmtCommAttack(BaseAttack.BaseAttack):
 
         # retrieve the mapping information
         mapped_ids, packet_start_idx, packet_end_idx = comm_interval["IDs"], comm_interval["Start"], comm_interval["End"]
+        # print(mapped_ids)
         while len(mapped_ids) > number_init_bots:
             rm_idx = randrange(0, len(mapped_ids))
             del mapped_ids[rm_idx]
@@ -383,7 +384,7 @@ class MembersMgmtCommAttack(BaseAttack.BaseAttack):
         # determine the roles of the IDs in the mapping communication-{initiator, responder}
         local_init_ids, external_init_ids, respnd_ids, messages = comm_proc.det_id_roles_and_msgs()
         # use these roles to determine which IDs are to be local and which external
-        local_ids, external_ids = comm_proc.det_ext_and_local_ids(self.PROB_RESPND_IS_LOCAL)
+        local_ids, external_ids = comm_proc.det_ext_and_local_ids()
 
         # retrieve and assign the IPs and MACs for the bots with respect to the given parameters
         # (IDs are always added to bot_configs in the same order under a given seed)

+ 12 - 145
code/ID2TLib/CommunicationProcessor.py

@@ -18,6 +18,12 @@ class CommunicationProcessor():
     """
 
     def __init__(self, packets:list, mtypes:dict, nat:bool):
+        """
+        Creates an instance of CommunicationProcessor.
+        :param packets: the list of abstract packets
+        :param mtypes: a dict containing an int to EnumType mapping of MessageTypes
+        :param nat: whether NAT is present in this network
+        """
         self.packets = packets
         self.mtypes = mtypes
         self.nat = nat
@@ -33,13 +39,6 @@ class CommunicationProcessor():
         self.local_init_ids = set(mapped_ids)
 
     def find_interval_most_comm(self, number_ids: int, max_int_time: float):
-        if self.nat:
-            return self._find_interval_most_comm_nat(number_ids, max_int_time)
-        else:
-            return self._find_interval_most_comm_nonat(number_ids, max_int_time)
-
-
-    def _find_interval_most_comm_nonat(self, number_ids: int, max_int_time: float):
         """
         Finds the time interval(s) of the given seconds with the most overall communication (i.e. requests and responses)
         that has at least number_ids communication initiators in it. 
@@ -55,7 +54,7 @@ class CommunicationProcessor():
         idx_low, idx_high = 0, 0  # the indices spanning the interval
         comm_sum = 0  # the communication sum of the current interval
         cur_highest_sum = 0  # the highest communication sum seen so far
-        ids = []  # the initiator IDs seen in the current interval in order of appearance
+        init_ids = []  # the initiator IDs seen in the current interval in order of appearance
         possible_intervals = []  # all intervals that have cur_highest_sum of communication and contain enough IDs
 
         # Iterate over all packets from start to finish and process the info of each packet.
@@ -66,7 +65,7 @@ class CommunicationProcessor():
      
             # if current interval time exceeds maximum time period, process information of the current interval
             if greater_than(cur_int_time, max_int_time) or idx_high >= len(packets):
-                interval_ids = set(ids)
+                interval_ids = set(init_ids)
                 # if the interval contains enough initiator IDs, add it to possible_intervals
                 if len(interval_ids) >= number_ids:
                     interval = {"IDs": sorted(interval_ids), "Start": idx_low, "End": idx_high-1}
@@ -89,7 +88,7 @@ class CommunicationProcessor():
                 # of this packet from the initiator list and update comm_sum
                 if mtypes[int(cur_packet["Type"])] != MessageType.TIMEOUT:
                     comm_sum -= 1
-                    del ids[0]
+                    del init_ids[0]
 
                 idx_low += 1
                 cur_int_time = float(packets[idx_high]["Time"]) - float(packets[idx_low]["Time"])
@@ -99,149 +98,17 @@ class CommunicationProcessor():
             cur_mtype = mtypes[int(cur_packet["Type"])]
             # if message is request, add src to initiator list
             if MessageType.is_request(cur_mtype):
-                ids.append(cur_packet["Src"])
+                init_ids.append(cur_packet["Src"])
                 comm_sum += 1
             # if message is response, add dst to initiator list
             elif MessageType.is_response(cur_mtype):
-                ids.append(cur_packet["Dst"])
+                init_ids.append(cur_packet["Dst"])
                 comm_sum += 1
 
             idx_high += 1
 
         return possible_intervals
 
-
-    def _find_interval_most_comm_nat(self, number_ids: int, max_int_time: float):
-        """
-        Finds the time interval(s) of the given seconds with the most communication (i.e. requests and responses) 
-        by the most number_ids communicative initiator IDs of the interval.
-        :param number_ids: The number of initiator IDs that have to exist in the interval(s)
-        :param max_int_time: The maximum time period of the interval
-        :return: A list of triples, where each triple contains the initiator IDs, the start index and the end index
-                 of the respective interval in that order. The indices are with respect to self.packets
-        """
-
-        def get_nez_comm_amounts():
-            """
-            Filters out all comm_amounts that have 0 as value.
-
-            :return: a dict with initiator IDs as keys and their non-zero communication amount as value
-            """
-
-            nez_comm_amounts = dict()
-            # Iterate over comm_amounts dict and add every entry
-            # with non-zero comm_amount to new dict.
-            for id_ in comm_amounts:
-                amount = comm_amounts[id_]
-                if amount > 0:
-                    nez_comm_amounts[id_] = amount
-            return nez_comm_amounts
-
-        def change_comm_amounts(packet: dict, add:bool=True):
-            """
-            Changes the communication amount, stored in comm_amounts, of the initiating ID with respect to the
-            packet specified by the given index.
-
-            :param packet: the packet to be processed, containing src and dst ID
-            :param add: If add is True, 1 is added to the communication amount of the IDs, otherwise 1 is subtracted
-            """
-
-            change = 1 if add else -1
-            mtype = mtypes[int(packet["Type"])]
-            id_src, id_dst = packet["Src"], packet["Dst"]
-            # if message is request, src is initiator
-            if MessageType.is_request(mtype):
-                # if src exists in comm_amounts, add 1 to its amount
-                if id_src in comm_amounts:
-                    comm_amounts[id_src] += change
-                # else if op is add, add the ID with comm value 1 to comm_amounts
-                elif change > 0:
-                    comm_amounts[id_src] = 1
-            # if message is response, dst is initiator
-            elif MessageType.is_response(mtype):
-                # if src exists in comm_amounts, add 1 to its amount
-                if id_dst in comm_amounts:
-                    comm_amounts[id_dst] += change
-                # else if op is add, add the ID with comm value 1 to comm_amounts
-                elif change > 0:
-                    comm_amounts[id_dst] = 1
-
-        def get_comm_amount_first_ids():
-            """
-            Finds the number_ids IDs that communicate the most with respect to nez_comm_amounts
-            :return: The picked IDs as a list and their summed message amount as a tuple like (IDs, sum).
-            """
-
-            picked_ids = []  # the IDs that have been picked
-            summed_comm_amount = 0  # the summed communication amount of all picked IDs
-            # sort the comm amounts to easily access the IDs with the most communication
-            sorted_comm_amounts = sorted(nez_comm_amounts.items(), key=lambda x: x[1], reverse=True)
-
-            # iterate over the sorted communication amounts
-            for id_, amount in sorted_comm_amounts:
-                count_picked_ids = len(picked_ids)
-
-                # if enough IDs have been found, stop
-                if count_picked_ids >= number_ids:
-                    break
-
-                # else pick this ID
-                picked_ids.append(id_)
-                summed_comm_amount += amount
-
-            return picked_ids, summed_comm_amount
-
-        # setup initial variables
-        packets = self.packets
-        mtypes = self.mtypes
-        idx_low, idx_high = 0, 0  # the indices spanning the interval
-        cur_highest_sum = 0  # the highest communication sum seen so far
-        # a dict containing information about what initiator ID has communicated how much
-        comm_amounts = {}  # entry is a tuple of (ID, amount)
-        possible_intervals = []  # all intervals that have cur_highest_sum of communication and contain enough IDs
-
-        # Iterate over all packets from start to finish and process the info of each packet.
-        # Similar to a Sliding Window approach.
-        while True:
-            if idx_high < len(packets):
-                cur_int_time = float(packets[idx_high]["Time"]) - float(packets[idx_low]["Time"])
-     
-            # if current interval time exceeds maximum time period, process information of the current interval
-            if greater_than(cur_int_time, max_int_time) or idx_high >= len(packets):
-                # filter out all IDs with a zero amount of communication for the current interval
-                nez_comm_amounts = get_nez_comm_amounts()
-                # if the interval contains enough initiator IDs, add it to possible_intervals
-                if len(nez_comm_amounts) >= number_ids:
-                    # pick the most communicative IDs and store their sum of communication
-                    picked_ids, comm_sum = get_comm_amount_first_ids()
-                    interval = {"IDs": picked_ids, "Start": idx_low, "End": idx_high-1}
-
-                    # reset possible intervals if new maximum of communication is found
-                    if comm_sum > cur_highest_sum:
-                        possible_intervals = [interval]
-                        cur_highest_sum = comm_sum
-                    # append otherwise
-                    elif comm_sum == cur_highest_sum:
-                        possible_intervals.append(interval)
-
-                # stop if all packets have been processed
-                if idx_high >= len(packets):
-                    break
-
-            # let idx_low "catch up" so that the current interval time fits into the maximum time period again
-            while greater_than(cur_int_time, max_int_time):
-                # adjust communication amounts to discard the earliest packet of the current interval
-                change_comm_amounts(packets[idx_low], add=False)
-                idx_low += 1
-                cur_int_time = float(packets[idx_high]["Time"]) - float(packets[idx_low]["Time"])
-
-            # consume the new packet at idx_high and process its information
-            change_comm_amounts(packets[idx_high])
-            idx_high += 1
-
-        return possible_intervals
-
-
     def det_id_roles_and_msgs(self):
         """
         Determine the role of every mapped ID. The role can be initiator, responder or both.
@@ -333,7 +200,7 @@ class CommunicationProcessor():
         # return the retrieved information
         return self.local_init_ids, self.external_init_ids, self.respnd_ids, self.messages
 
-    def det_ext_and_local_ids(self, prob_rspnd_local: int):
+    def det_ext_and_local_ids(self, prob_rspnd_local: int=0):
         """
         Map the given IDs to a locality (i.e. local or external} considering the given probabilities.