Exemplo n.º 1
0
    def do_flow_mod(self, event=None):
        """
        If the event is not specified, then issues a flow mod with random src
        and dst ports; all the other fields will match against the trigger event
        saved earlier. Does not issue pkt_out.
        
        Otherwise, does a normal flow_mod.
        
        """
        msg = of.ofp_flow_mod()

        # Normal flow-mod
        if event:
            msg.match = of.ofp_match.from_packet(event.parse())
            msg.actions.append(of.ofp_action_output(port=get_the_other_port(event.port)))
            msg.buffer_id = event.ofp.buffer_id
            
            # Save the trigger event for later matching.
            if msg.match.tp_dst == TRIGGER_PORT:
                with self.lock:
                    self.trigger_event = event
                mylog('Received trigger event. Trigger event.parse() =', pretty_dict(dictify(event.parse())))
            
            mylog('Installed flow:', pretty_dict(dictify(msg.match)))
            
        # Special flow-mod that generates random source/dst ports.
        else:
            with self.lock:
                assert self.trigger_event
                trigger_packet = func_cache(self.trigger_event.parse)
                msg.match = of.ofp_match.from_packet(trigger_packet)
                msg.actions.append(of.ofp_action_output(port=get_the_other_port(self.trigger_event.port)))
            msg.match.tp_dst = random.randint(10, 65000)
            msg.match.tp_src = random.randint(10, 65000)
            
        current_time = time.time()
        with self.lock:
            (count, start, _) = self.flow_mod_stat
            if start is None: start = current_time
            self.flow_mod_stat = (count + 1, start, current_time)

        msg.idle_timeout = IDLE_TIMEOUT
        msg.hard_timeout = HARD_TIMEOUT

        if (not USE_LIMITER) or (USE_LIMITER and self.flow_mod_limiter.to_forward_packet()):
            self._of_send(msg)
        
        self.flow_mod_queue.put((current_time, event.parse()))
Exemplo n.º 2
0
    def _install_rule(self, event, packet, outport, tp_dst=None, idle_timeout=IDLE_TIMEOUT):
        """
        Installs a rule for any incoming packet, doing what a learning switch
        should do.
        
        """
        msg = of.ofp_flow_mod()
        msg.match = of.ofp_match.from_packet(packet)
        msg.idle_timeout = idle_timeout
        msg.hard_timeout = HARD_TIMEOUT
        msg.actions.append(of.ofp_action_output(port=outport))

        with exp_control.lock:
            exp_control.flow_mod_count += 1
            install_bogus_rules = exp_control.install_bogus_rules

        # Install a rule with a randomly generated dest mac address that no
        # one will ever match against.
        if install_bogus_rules:
            # mac_addr_list = ['0' + str(random.randint(1,9)) for _ in range(6)]
            # msg.match.dl_src = EthAddr(':'.join(mac_addr_list))
            msg.match.tp_dst = random.randint(10, 65000)
            msg.match.tp_src = random.randint(10, 65000)
            msg.buffer_id = event.ofp.buffer_id
            mylog("Installing a bogus flow.")

        # Create a rule that matches with the incoming packet. When buffer ID is
        # specified, the flow mod command is automatically followed by a packet-
        # out command.
        elif tp_dst is None:
            msg.buffer_id = event.ofp.buffer_id
            with exp_control.lock:
                exp_control.pkt_out_count += 1
            mylog("installing flow for %s.%i -> %s.%i" % (packet.src, event.port, packet.dst, outport))

        # Create a rule with a specific dest port.
        else:
            msg.match.tp_dst = tp_dst
            mylog("Installing rule for tp_dst =", tp_dst)

        current_time = time.time()
        with exp_control.lock:
            if exp_control.flow_mod_start_time is None:
                exp_control.flow_mod_start_time = current_time
            exp_control.flow_mod_end_time = current_time

        mylog("Flow_mod:", pretty_dict(dictify(msg)))
        self.connection.send(msg)
Exemplo n.º 3
0
    def _is_relevant_packet(self, event, packet):
        """ 
        Sanity check to make sure we deal with experimental traffic only.
        Otherwise, returns False.
        
        """        
        mylog('zzzz inport =', event.port)
        
        if not self.transparent:
            if packet.type == packet.LLDP_TYPE or packet.dst.isBridgeFiltered():
                mylog('pkt_in: Rejected packet LLDP or BridgeFiltered:', packet, repr(packet), dictify(packet))
                self._drop(event)
                return False

        if event.port not in SWITCH_PORT_LIST:
            mylog('pkt_in: Rejected packet: invalid port', packet, repr(packet), dictify(packet))
            self._drop(event)
            return False

        if packet.dst.isMulticast():
            self.do_pkt_out(event) 
            return False
                
        return True
Exemplo n.º 4
0
    def _handle_pkt_in_helper(self, event):

        packet = event.parse()
        current_time = time.time()

        with exp_control.lock:
            flow_stat_interval = exp_control.flow_stat_interval

        # Obtain flow stats once in a while.
        if flow_stat_interval:
            if current_time - self.last_flow_stat_time > flow_stat_interval:
                self.last_flow_stat_time = current_time
                self.connection.send(of.ofp_stats_request(body=of.ofp_flow_stats_request()))

        # There are just packets that we don't care.
        if not self._is_relevant_packet(event, packet):
            mylog("pkt_in: Rejected packet:", packet, repr(packet), dictify(packet))
            return

        # Throttle packet-in events if need be.
        if exp_control.emulate_hp_switch:
            if not self.limiter_pkt_in.to_forward_packet():
                return

        # Count packet-in events.
        with exp_control.lock:
            learning_switch = exp_control.learning
            exp_control.pkt_in_count += 1
            if exp_control.pkt_in_start_time is None:
                exp_control.pkt_in_start_time = current_time
            exp_control.pkt_in_end_time = current_time

        # Count number of packet-out events if the switch does not install
        # rules.
        if not learning_switch:
            with exp_control.lock:
                exp_control.pkt_out_count += 1
            self._drop(event)
            return

        outport = get_the_other_port(event.port)

        # Throttle flow-mod events and pkt-out events if need be.
        if exp_control.emulate_hp_switch:
            if self.limiter_flow_mod.to_forward_packet():
                # flow-mod and pkt-out at 50 pps
                pass
            else:
                # pkt-out at 50 pps, so regardless, total pkt-out at 100 pps
                if self.limiter_pkt_out.to_forward_packet():
                    self._packet_out(event)
                return

        # Automatically learns new flows, as a normal learning switch would do.
        if exp_control.auto_install_rules:
            self._install_rule(event, packet, outport)
            return

        # Manually install rules in the port range.
        with exp_control.lock:
            tp_dst_range = exp_control.manual_install_tp_dst_range[:]
            gap_ms = exp_control.manual_install_gap_ms

        for tp_dst in range(*tp_dst_range):

            # Keep going until the exp_control client decides to stop it.
            with exp_control.lock:
                manual_active = exp_control.manual_install_active
            if not manual_active:
                break

            self._install_rule(event, packet, outport, tp_dst)
            time.sleep(gap_ms / 1000.0)