예제 #1
0
    def all_timeout(self, current_time):
        """
        Also timeout flows in secondary table
        """
        # timeout primary table

        #expired = [k for k, v in self.table.items() if v.active and self.check_timeout(v, current_time)]

        should_expired = []
        while len(self.should_active) > 0:
            earliest = self.should_active[0]
            if self.check_delta(current_time, earliest[1], self.timeout):
                should_expired.append(self.should_active.pop(0)[0])
            else:
                break

        should_active_ids = [i[0] for i in self.should_active]

        for id in should_expired:
            flow = self.table[id]
            if not flow.active or id in should_active_ids:
                continue
            self.deactivate_flow(id)

            # Rule #1, fixed timeout
            if self.timeout_policy == 1:

                # a miss happens for a second time, insert into cache when timed out
                # in reality, controller will tell switch this information
                if self.table[id].num_rules() >= self.threshold:
                    Output.DEBUG("Adding to secondary")
                    self.secondary_table[id] = current_time + (
                        self.timeout *
                        self.cache_multiplier) / 1000  # in seconds
            # Rule #2, timeout based on last rules

            elif self.timeout_policy == 2:

                # the threshold must be greater than 2, because of course
                # TODO: make it variable
                flow = self.table[id]
                if flow.num_rules() >= self.threshold:
                    last_rule = flow.rules[-1]
                    second_last = flow.rules[-2]
                    cachetime = current_time + (last_rule.first_seen -
                                                second_last.last_update) * 1.1
                    if (last_rule.first_seen - second_last.last_update) > 1:
                        cachetime = current_time + 1  # greater than 1 second make it 1 second

                    self.secondary_table[id] = cachetime

        # timeout secondary table
        expired = [
            k for k, v in self.secondary_table.items() if current_time > v
        ]

        for k in expired:
            Output.DEBUG("deleting " + k + " from secondary")
            del self.secondary_table[k]
예제 #2
0
    def existing_flow(self, packet):
        id = packet.get_id()
        if not self.if_flow_exists(id):
            raise Exception("Flow does not exist")

        flow = self.table[id]
        latest_rule = None

        if flow.active:
            latest_rule = flow.rules[-1]
        elif self.if_secondary_exists(id) and not flow.active:
            self.table[id].active = True
            self.secondary_table.remove(id)
            self.current_active_flow += 1
            latest_rule = flow.rules[-1]
        else:
            latest_rule = flow.create_rule(packet.timestamp)
            self.missed += 1
            self.total_rules += 1
            self.current_active_flow += 1
            flow.active = True
            Output.DEBUG("Added new rule")

        flow.last_update = packet.timestamp
        latest_rule.new_packet(packet)

        self.table[id] = flow

        if self.current_active_flow > self.max_flow_count:
            self.max_flow_count = self.current_active_flow
예제 #3
0
    def existing_flow(self, packet):
        id = packet.get_id()
        if not self.if_flow_exists(id):
            raise Exception("Flow does not exist")

        flow = self.table[id]
        latest_rule = None
        cur_time = packet.timestamp

        if flow.active:
            latest_rule = flow.rules[-1]
        elif self.if_secondary_exists(id) and not flow.active:
            # in secondary table
            self.table[id].active = True
            del self.secondary_table[id]  # remove entry in cache
            self.current_active_flow += 1
            latest_rule = flow.rules[-1]

        else:
            latest_rule = flow.create_rule(cur_time)
            self.missed += 1
            self.total_rules += 1
            self.current_active_flow += 1
            flow.active = True
            Output.DEBUG("Added new rule")

        flow.last_update = cur_time
        latest_rule.new_packet(packet)

        self.table[id] = flow

        if self.current_active_flow > self.max_flow_count:
            self.max_flow_count = self.current_active_flow

        self.should_active.append((flow.id, flow.last_update))
예제 #4
0
    def existing_flow(self, packet):
        ''' 
        Handles cases where a flow already exists.
        If it's active, update the last rule in rule list.
        If it's not active, a new rule needs to be created.
        '''
        id = packet.get_id()
        if not self.if_flow_exists(id):
            raise Exception("Flow does not exist")

        flow = self.table[id]
        latest_rule = None

        if flow.active:
            latest_rule = flow.rules[-1]
        else:
            latest_rule = flow.create_rule(packet.timestamp)
            self.missed += 1
            self.total_rules += 1
            self.current_active_flow += 1
            flow.active = True
            Output.DEBUG("Added new rule")

        flow.last_update = packet.timestamp
        latest_rule.new_packet(packet)

        self.table[id] = flow

        if self.current_active_flow > self.max_flow_count:
            self.max_flow_count = self.current_active_flow

        self.should_active.append((flow.id, flow.last_update))
예제 #5
0
    def check_timeout(self, flow, current_time):
        # converts to ms
        delta = (current_time - flow.last_update) * 1000

        if self.check_delta(current_time, flow.last_update, self.timeout):
            Output.DEBUG("Timing out " + flow.id)
            return True
        else:
            return False
예제 #6
0
    def check_timeout(self, flow, current_time):
        # converts to ms

        timeout = self.timeout_table[flow.id][-1]

        if self.check_delta(current_time, flow.last_update, timeout):
            Output.DEBUG("Timing out " + flow.id)
            return True
        else:
            return False
예제 #7
0
    def push_secondary(self, id):
        if len(self.secondary_table) > self.secondary_table_size:
            Output.DEBUG("Evicting: " + id)
            self.eviction_policy()

        self.secondary_table.append(id)
예제 #8
0
    def process_packet(self, timestamp, raw_packet):
        '''
        Process an IP packet and output statstics
        '''
        Output.VERBOSE("---------Processing Packet At Time:----------")
        Output.VERBOSE(datetime.utcfromtimestamp(timestamp))
        self.current_time = timestamp
        self.total_packets += 1

        if (self.current_time -
                self.last_dump_time) * 1000 > self.dump_interval:
            self.flow_table.all_timeout(self.current_time)
            self.output_statistics(self.to_file)
            self.last_dump_time = self.current_time

        try:
            eth = dpkt.ethernet.Ethernet(raw_packet)
        except Exception:
            return

        ip = eth.data

        if not isinstance(ip, dpkt.ip.IP):
            Output.VERBOSE("Not an IP packet")
            return

        packet = Packet(timestamp)
        packet.size = len(raw_packet)

        packet.eth_src = eth.src
        packet.eth_dst = eth.dst
        packet.eth_type = eth.type

        packet.ip_src = ip.src
        packet.ip_dst = ip.dst
        packet.ip_protocol = ip.p

        tcp, udp = None, None

        if packet.ip_protocol == IP_PROTOCOL.TCP:  # tcp
            tcp = ip.data
        elif packet.ip_protocol == IP_PROTOCOL.UDP:  # udp
            udp = ip.data
        else:
            Output.VERBOSE("Not TCP or UDP")
            return

        if tcp and type(tcp) == dpkt.tcp.TCP:
            packet.sport = tcp.sport
            packet.dport = tcp.dport
        elif udp and type(udp) == dpkt.udp.UDP:
            packet.sport = udp.sport
            packet.dport = udp.dport
        else:
            return

        id = packet.get_id()

        if self.flow_table.if_flow_exists(id):
            self.flow_table.existing_flow(packet)
        else:
            self.flow_table.non_existing_flow(packet)