예제 #1
0
  def simulate(self):
    simulation = self.initialize_simulation()

    # Some implementations send delete flow mods when disconnecting switches; ignore these flow_mods
    if self.ignore_trailing_flow_mod_deletes:
      # switch -> whether we have observed a flow_mod other than a trailing delete yet
      dpid2seen_non_delete = { switch.dpid : False for switch in simulation.topology.switches }

    # Reproduce the routing table state.
    all_flow_mods = []
    for next_event in self.event_list:
      if is_flow_mod(next_event):
        msg.special_event("Injecting %r" % next_event)
        all_flow_mods.append(next_event)
      else:
        msg.openflow_event("Injecting %r" % next_event)
      next_event.manually_inject(simulation)

    # Now filter out all flow_mods that don't correspond to an entry in the
    # final routing table. Do that by walking backwards through the flow_mods,
    # and checking if they match the flow table. If so, add it to list, and
    # remove all flow entries that currently match it to filter overlapping
    # flow_mods from earlier in the event_list.
    relevant_flow_mods = []
    for last_event in reversed(all_flow_mods):
      switch = simulation.topology.get_switch(last_event.dpid)

      # Ignore all trailing flow mod deletes
      if self.ignore_trailing_flow_mod_deletes:
        flow_mod_command = last_event.get_packet().command
        if (not dpid2seen_non_delete[switch.dpid] and
            (flow_mod_command == OFPFC_DELETE or flow_mod_command == OFPFC_DELETE_STRICT)):
          continue
        else:
          dpid2seen_non_delete[switch.dpid] = True

      if switch.table.matching_entries(last_event.get_packet().match) != []:
        relevant_flow_mods.append(last_event)
        switch.table.remove_matching_entries(last_event.get_packet().match)

    relevant_flow_mods.reverse()

    # Print filtered flow mods
    print "\n"
    msg.event("Filtered flow mods:")
    for next_event in relevant_flow_mods:
      print "%r" % next_event
    print "\n"

    # Add back removed entries.
    for flow_mod_event in relevant_flow_mods:
      flow_mod_event.manually_inject(simulation)

    # Now print flow tables of each switch.
    msg.event("Flow tables:")
    for switch in simulation.topology.switches:
      print "Switch %s" % switch.dpid
      switch.show_flow_table()

    return simulation
예제 #2
0
파일: fuzzer.py 프로젝트: MurphyMc/sts
  def loop(self):
    if self.steps:
      end_time = self.logical_time + self.steps
    else:
      end_time = sys.maxint

    exit_code = 0
    self.interrupted = False
    old_interrupt = None

    def interrupt(sgn, frame):
      msg.interactive("Interrupting fuzzer, dropping to console (press ^C again to terminate)")
      signal.signal(signal.SIGINT, self.old_interrupt)
      self.old_interrupt = None
      self.interrupted = True
      raise KeyboardInterrupt()

    self.old_interrupt = signal.signal(signal.SIGINT, interrupt)

    try:
      # Always connect to controllers explicitly
      self.simulation.connect_to_controllers()
      self._log_input_event(ConnectToControllers())

      if self.delay_startup:
        # Wait until the first OpenFlow message is received
        log.info("Waiting until first OpenfFlow message received..")
        while self.simulation.god_scheduler.pending_receives() == []:
          self.simulation.io_master.select(self.delay)

      while self.logical_time < end_time:
        self.logical_time += 1
        try:
          self.trigger_events()
          msg.event("Round %d completed." % self.logical_time)
          halt = self.maybe_check_invariant()
          if halt:
            exit_code = 5
            break
          self.maybe_inject_trace_event()
          time.sleep(self.delay)
        except KeyboardInterrupt as e:
          if self.interrupted:
            interactive = Interactive(self.simulation_cfg, self._input_logger)
            interactive.simulate(self.simulation, bound_objects=( ('fuzzer', self), ))
            self.old_interrupt = signal.signal(signal.SIGINT, interrupt)
          else:
            raise e

      log.info("Terminating fuzzing after %d rounds" % self.logical_time)
      if self.print_buffers:
        self._print_buffers()

    finally:
      if self.old_interrupt:
        signal.signal(signal.SIGINT, self.old_interrupt)
      if self._input_logger is not None:
        self._input_logger.close(self, self.simulation_cfg)

    return exit_code
예제 #3
0
 def permit_dp_event(self, dp_event):
     """ Given a SwitchDpPacketOut event, permit it to be forwarded """
     # TODO(cs): self.forward_packet should not be externally visible!
     msg.event("Forwarding dataplane event")
     # Invoke superclass DpPacketOut handler
     self.handle_DpPacketOut(dp_event)
     self._remove_dp_event(dp_event)
예제 #4
0
 def permit_dp_event(self, dp_event):
     ''' Given a SwitchDpPacketOut event, permit it to be forwarded '''
     # TODO(cs): self.forward_packet should not be externally visible!
     msg.event("Forwarding dataplane event")
     # Invoke superclass DpPacketOut handler
     self.handle_DpPacketOut(dp_event)
     self._remove_dp_event(dp_event)
예제 #5
0
파일: entities.py 프로젝트: NetSys/sts
  def start(self):
    '''Start a new controller process based on the config's cmdline
    attribute. Registers the Popen member variable for deletion upon a SIG*
    received in the simulator process.'''
    msg.event("Starting controller %s" % (str(self.cid)))
    env = None

    if self.config.sync:
      # if a sync connection has been configured in the controller conf
      # launch the controller with environment variable 'sts_sync' set
      # to the appropriate listening port. This is quite a hack.
      env = os.environ.copy()
      port_match = re.search(r':(\d+)$', self.config.sync)
      if port_match is None:
        raise ValueError("sync: cannot find port in %s" % self.config.sync)
      port = port_match.group(1)
      env['sts_sync'] = "ptcp:0.0.0.0:%d" % (int(port),)

      if self.config.name == "pox":
        src_dir = os.path.join(os.path.dirname(__file__), "..")
        pox_ext_dir = os.path.join(self.config.cwd, "ext")
        if os.path.exists(pox_ext_dir):
          for f in ("sts/util/io_master.py", "sts/syncproto/base.py",
                    "sts/syncproto/pox_syncer.py", "sts/__init__.py",
                    "sts/util/socket_mux/__init__.py",
                    "sts/util/socket_mux/pox_monkeypatcher.py",
                    "sts/util/socket_mux/base.py",
                    "sts/util/socket_mux/server_socket_multiplexer.py"):
            src_path = os.path.join(src_dir, f)
            if not os.path.exists(src_path):
              raise ValueError("Integrity violation: sts sync source path %s (abs: %s) does not exist" %
                  (src_path, os.path.abspath(src_path)))
            dst_path = os.path.join(pox_ext_dir, f)
            dst_dir = os.path.dirname(dst_path)
            init_py = os.path.join(dst_dir, "__init__.py")
            if not os.path.exists(dst_dir):
              os.makedirs(dst_dir)

            if not os.path.exists(init_py):
              open(init_py, "a").close()

            if os.path.islink(dst_path):
              # remove symlink and recreate
              os.remove(dst_path)

            if not os.path.exists(dst_path):
              rel_link = os.path.abspath(src_path)
              self.log.debug("creating symlink %s -> %s", rel_link, dst_path)
              os.symlink(rel_link, dst_path)
        else:
          self.log.warn("Could not find pox ext dir in %s. Cannot check/link in sync module" % pox_ext_dir)

    self.log.info("Launching controller %s: %s" % (self.label, " ".join(self.config.expanded_cmdline)))
    self.process = popen_filtered("[%s]"%self.label, self.config.expanded_cmdline, self.config.cwd, env=env)
    self._register_proc(self.process)

    if self.config.sync:
      self.sync_connection = self.sync_connection_manager.connect(self, self.config.sync)

    self.alive = True
예제 #6
0
 def sever_link(self, link):
     msg.event("Cutting link %s" % str(link))
     if link not in self.network_links:
         raise ValueError("unknown link %s" % str(link))
     if link in self.cut_links:
         raise RuntimeError("link %s already cut!" % str(link))
     self.cut_links.add(link)
     link.start_software_switch.take_port_down(link.start_port)
예제 #7
0
 def drop_dp_event(self, dp_event):
     '''
 Given a SwitchDpPacketOut event, remove it from our buffer, and do not forward.
 Return the dropped event.
 '''
     msg.event("Dropping dataplane event")
     self._remove_dp_event(dp_event)
     return dp_event
예제 #8
0
 def drop_dp_event(self, dp_event):
     """
 Given a SwitchDpPacketOut event, remove it from our buffer, and do not forward.
 Return the dropped event.
 """
     msg.event("Dropping dataplane event")
     self._remove_dp_event(dp_event)
     return dp_event
예제 #9
0
 def sever_link(self, link):
     msg.event("Cutting link %s" % str(link))
     if link not in self.network_links:
         raise ValueError("unknown link %s" % str(link))
     if link in self.cut_links:
         raise RuntimeError("link %s already cut!" % str(link))
     self.cut_links.add(link)
     link.start_software_switch.take_port_down(link.start_port)
예제 #10
0
파일: topology.py 프로젝트: colin-scott/sts
 def drop_dp_event(self, dp_event):
   '''
   Given a SwitchDpPacketOut event, remove it from our buffer, and do not forward.
   Return the dropped event.
   '''
   msg.event("Dropping dataplane event")
   self.buffered_dp_out_events.remove(dp_event)
   self.dropped_dp_events.append(dp_event)
   return dp_event
예제 #11
0
파일: entities.py 프로젝트: colin-scott/sts
  def kill(self):
    '''Kill the process the controller is running in.'''
    msg.event("Killing controller %s" % (str(self.uuid)))
    if self.sync_connection:
      self.sync_connection.close()

    kill_procs([self.process])
    self._unregister_proc(self.process)
    self.alive = False
    self.process = None
예제 #12
0
파일: fuzzer.py 프로젝트: MurphyMc/sts
 def fuzz_traffic(self):
   if not self.simulation.dataplane_trace:
     # randomly generate messages from switches
     for host in self.simulation.topology.hosts:
       if self.random.random() < self.params.traffic_generation_rate:
         if len(host.interfaces) > 0:
           msg.event("injecting a random packet")
           traffic_type = "icmp_ping"
           # Generates a packet, and feeds it to the software_switch
           dp_event = self.traffic_generator.generate(traffic_type, host)
           self._log_input_event(TrafficInjection(), dp_event=dp_event)
예제 #13
0
 def recover_switch(self, software_switch, down_controller_ids=None):
     msg.event("Rebooting software_switch %s" % str(software_switch))
     if down_controller_ids is None:
         down_controller_ids = set()
     if software_switch not in self.failed_switches:
         log.warn("Switch %s not currently down. (Currently down: %s)" %
                  (str(software_switch), str(self.failed_switches)))
     connected_to_at_least_one = software_switch\
                                  .recover(down_controller_ids=down_controller_ids)
     if connected_to_at_least_one:
         self.failed_switches.remove(software_switch)
     return connected_to_at_least_one
예제 #14
0
 def recover_switch(self, software_switch, down_controller_ids=None):
     msg.event("Rebooting software_switch %s" % str(software_switch))
     if down_controller_ids is None:
         down_controller_ids = set()
     if software_switch not in self.failed_switches:
         log.warn(
             "Switch %s not currently down. (Currently down: %s)" % (str(software_switch), str(self.failed_switches))
         )
     connected_to_at_least_one = software_switch.recover(down_controller_ids=down_controller_ids)
     if connected_to_at_least_one:
         self.failed_switches.remove(software_switch)
     return connected_to_at_least_one
예제 #15
0
파일: fuzzer.py 프로젝트: I201821180B/sts
 def fuzz_traffic(self):
     if not self.simulation.dataplane_trace:
         # randomly generate messages from switches
         for host in self.simulation.topology.hosts:
             if self.random.random() < self.params.traffic_generation_rate:
                 if len(host.interfaces) > 0:
                     msg.event("injecting a random packet")
                     traffic_type = "icmp_ping"
                     # Generates a packet, and feeds it to the software_switch
                     dp_event = self.traffic_generator.generate(
                         traffic_type, host)
                     self._log_input_event(TrafficInjection(),
                                           dp_event=dp_event)
예제 #16
0
파일: entities.py 프로젝트: jefflai2/sts
 def kill(self):
   ''' Kill the process the controller is running in '''
   if self.state != ControllerState.ALIVE:
     self.log.warn("Killing controller %s when it is not alive!" % self.label)
     return
   msg.event("Killing controller %s" % self.cid)
   kill_procs([self.process])
   if self.config.kill_cmd != "":
     self.log.info("Killing controller %s: %s" % (self.label, " ".join(self.config.expanded_kill_cmd)))
     popen_filtered("[%s]" % self.label, self.config.expanded_kill_cmd, self.config.cwd)
   self._unregister_proc(self.process)
   self.process = None
   self.state = ControllerState.DEAD
예제 #17
0
 def kill(self):
     """ Kill the process the controller is running in """
     if self.state != ControllerState.ALIVE:
         self.log.warn("Killing controller %s when it is not alive!" %
                       self.label)
         return
     msg.event("Killing controller %s (pid %d)" % (self.cid, self.pid))
     kill_procs([self.process])
     if self.config.kill_cmd not in ["", None]:
         self.log.info(
             "Killing controller %s: %s" %
             (self.label, " ".join(self.config.expanded_kill_cmd)))
         popen_filtered("[%s]" % self.label, self.config.expanded_kill_cmd,
                        self.config.cwd)
     self._unregister_proc(self.process)
     self.process = None
     self.state = ControllerState.DEAD
예제 #18
0
파일: fuzzer.py 프로젝트: colin-scott/sts
  def loop(self):
    if self.steps:
      end_time = self.logical_time + self.steps
    else:
      end_time = sys.maxint

    try:
      while self.logical_time < end_time:
        self.logical_time += 1
        self.trigger_events()
        msg.event("Round %d completed." % self.logical_time)
        halt = self.maybe_check_invariant()
        if halt:
          break
        self.maybe_inject_trace_event()
        time.sleep(self.delay)
    finally:
      if self._input_logger is not None:
        self._input_logger.close(self.simulation_cfg)
예제 #19
0
파일: fuzzer.py 프로젝트: I201821180B/sts
    def loop(self):
        if self.steps:
            end_time = self.logical_time + self.steps
        else:
            end_time = sys.maxint

        try:
            while self.logical_time < end_time:
                self.logical_time += 1
                self.trigger_events()
                msg.event("Round %d completed." % self.logical_time)
                halt = self.maybe_check_invariant()
                if halt:
                    break
                self.maybe_inject_trace_event()
                time.sleep(self.delay)
        finally:
            if self._input_logger is not None:
                self._input_logger.close(self.simulation_cfg)
예제 #20
0
파일: fuzzer.py 프로젝트: NetSys/sts
 def check_migrations(self):
     for access_link in list(self.simulation.topology.access_links):
         if self.random.random() < self.params.host_migration_rate:
             old_ingress_dpid = access_link.switch.dpid
             old_ingress_port_no = access_link.switch_port.port_no
             live_edge_switches = list(self.simulation.topology.live_edge_switches)
             if len(live_edge_switches) > 0:
                 new_switch = random.choice(live_edge_switches)
                 new_switch_dpid = new_switch.dpid
                 new_port_no = max(new_switch.ports.keys()) + 1
                 msg.event("Migrating host %s" % str(access_link.host))
                 self.simulation.topology.migrate_host(
                     old_ingress_dpid, old_ingress_port_no, new_switch_dpid, new_port_no
                 )
                 self._log_input_event(
                     HostMigration(
                         old_ingress_dpid, old_ingress_port_no, new_switch_dpid, new_port_no, access_link.host.name
                     )
                 )
                 self._send_initialization_packet(access_link.host, self_pkt=True)
예제 #21
0
    def start(self, multiplex_sockets=False):
        """
    Start a new POX controller process based on the config's start_cmd
    attribute. Registers the Popen member variable for deletion upon a SIG*
    received in the simulator process
    """
        self.log.info(self.welcome_msg)

        if self.state != ControllerState.DEAD:
            self.log.warn(
                "Starting controller %s when controller is not dead!" %
                self.label)
            return

        msg.event("Starting POX controller %s" % (str(self.cid)))
        env = None

        if self.config.sync:
            # If a sync connection has been configured in the controller conf
            # launch the controller with environment variable 'sts_sync' set
            # to the appropriate listening port. This is quite a hack.
            env = os.environ.copy()
            port_match = re.search(r':(\d+)$', self.config.sync)
            if port_match is None:
                raise ValueError("sync: cannot find port in %s" %
                                 self.config.sync)
            port = port_match.group(1)
            env['sts_sync'] = "ptcp:0.0.0.0:%d" % (int(port), )

        if self.config.sync or multiplex_sockets:
            src_dir = os.path.join(os.path.dirname(__file__), "../../")
            pox_ext_dir = os.path.join(self.config.cwd, "ext")
            if os.path.exists(pox_ext_dir):
                for f in ("sts/util/io_master.py", "sts/syncproto/base.py",
                          "sts/syncproto/pox_syncer.py", "sts/__init__.py",
                          "sts/util/socket_mux/__init__.py",
                          "sts/util/socket_mux/pox_monkeypatcher.py",
                          "sts/util/socket_mux/base.py",
                          "sts/util/socket_mux/server_socket_multiplexer.py"):
                    src_path = os.path.join(src_dir, f)
                    if not os.path.exists(src_path):
                        raise ValueError(
                            "Integrity violation: sts sync source path %s (abs: %s) "
                            "does not exist" %
                            (src_path, os.path.abspath(src_path)))
                    dst_path = os.path.join(pox_ext_dir, f)
                    dst_dir = os.path.dirname(dst_path)
                    init_py = os.path.join(dst_dir, "__init__.py")
                    if not os.path.exists(dst_dir):
                        os.makedirs(dst_dir)
                    if not os.path.exists(init_py):
                        open(init_py, "a").close()
                    if os.path.islink(dst_path):
                        # Remove symlink and recreate
                        os.remove(dst_path)
                    if not os.path.exists(dst_path):
                        rel_link = os.path.abspath(src_path)
                        self.log.debug("Creating symlink %s -> %s", rel_link,
                                       dst_path)
                        os.symlink(rel_link, dst_path)
            else:
                self.log.warn("Could not find pox ext dir in %s. " +
                              "Cannot check/link in sync module" % pox_ext_dir)

        if self.config.start_cmd in ["", None]:
            raise RuntimeError("No command found to start controller %s!" %
                               self.label)

        start_cmd = getattr(self.config, "expanded_start_cmd",
                            self.config.start_cmd)
        self.log.info("Launching controller %s: %s" %
                      (self.label, " ".join(start_cmd)))

        launch_in_network_namespace = getattr(self.config,
                                              "launch_in_network_namespace",
                                              False)
        if launch_in_network_namespace:
            (self.process, self.guest_eth_addr, self.host_device) = \
                launch_namespace(
                  " ".join(start_cmd),
                  self.config.address, self.cid,
                  host_ip_addr_str=IPAddressSpace.find_unclaimed_address(
                    ip_prefix=self.config.address),
                  cwd=self.config.cwd, env=env)
        else:
            self.process = popen_filtered("[%s]" % self.label, start_cmd,
                                          self.config.cwd, env)
        self._register_proc(self.process)
        if self.config.sync:
            self.sync_connection = self.sync_connection_manager.connect(
                self, self.config.sync)
        self._check_snapshot_connect()
        self.state = ControllerState.ALIVE
예제 #22
0
 def repair_link(self, link):
     msg.event("Restoring link %s" % str(link))
     if link not in self.network_links:
         raise ValueError("Unknown link %s" % str(link))
     link.start_software_switch.bring_port_up(link.start_port)
     self.cut_links.remove(link)
예제 #23
0
 def crash_switch(self, software_switch):
     msg.event("Crashing software_switch %s" % str(software_switch))
     software_switch.fail()
     self.failed_switches.add(software_switch)
예제 #24
0
 def reboot_controller(controller):
   msg.event("Restarting controller %s" % str(controller))
   controller.start()
예제 #25
0
파일: topology.py 프로젝트: MurphyMc/sts
 def delay_dp_event(self, dp_event):
     msg.event("Delaying dataplane event")
     # (Monkey patch on a delay counter)
     if not hasattr(dp_event, "delayed_rounds"):
         dp_event.delayed_rounds = 0
     dp_event.delayed_rounds += 1
예제 #26
0
  def start(self, multiplex_sockets=False):
    """
    Start a new POX controller process based on the config's start_cmd
    attribute. Registers the Popen member variable for deletion upon a SIG*
    received in the simulator process
    """
    self.log.info(self.welcome_msg)

    if self.state != ControllerState.DEAD:
      self.log.warn(
        "Starting controller %s when controller is not dead!" % self.label)
      return

    msg.event("Starting POX controller %s" % (str(self.cid)))
    env = None

    if self.config.sync:
      # If a sync connection has been configured in the controller conf
      # launch the controller with environment variable 'sts_sync' set
      # to the appropriate listening port. This is quite a hack.
      env = os.environ.copy()
      port_match = re.search(r':(\d+)$', self.config.sync)
      if port_match is None:
        raise ValueError("sync: cannot find port in %s" % self.config.sync)
      port = port_match.group(1)
      env['sts_sync'] = "ptcp:0.0.0.0:%d" % (int(port),)

    if self.config.sync or multiplex_sockets:
      src_dir = os.path.join(os.path.dirname(__file__), "../../")
      pox_ext_dir = os.path.join(self.config.cwd, "ext")
      if os.path.exists(pox_ext_dir):
        for f in ("sts/util/io_master.py", "sts/syncproto/base.py",
                  "sts/syncproto/pox_syncer.py", "sts/__init__.py",
                  "sts/util/socket_mux/__init__.py",
                  "sts/util/socket_mux/pox_monkeypatcher.py",
                  "sts/util/socket_mux/base.py",
                  "sts/util/socket_mux/server_socket_multiplexer.py"):
          src_path = os.path.join(src_dir, f)
          if not os.path.exists(src_path):
            raise ValueError(
              "Integrity violation: sts sync source path %s (abs: %s) "
              "does not exist" % (src_path, os.path.abspath(src_path)))
          dst_path = os.path.join(pox_ext_dir, f)
          dst_dir = os.path.dirname(dst_path)
          init_py = os.path.join(dst_dir, "__init__.py")
          if not os.path.exists(dst_dir):
            os.makedirs(dst_dir)
          if not os.path.exists(init_py):
            open(init_py, "a").close()
          if os.path.islink(dst_path):
            # Remove symlink and recreate
            os.remove(dst_path)
          if not os.path.exists(dst_path):
            rel_link = os.path.abspath(src_path)
            self.log.debug("Creating symlink %s -> %s", rel_link, dst_path)
            os.symlink(rel_link, dst_path)
      else:
        self.log.warn("Could not find pox ext dir in %s. " +
                      "Cannot check/link in sync module" % pox_ext_dir)

    if self.config.start_cmd in ["", None]:
      raise RuntimeError(
        "No command found to start controller %s!" % self.label)

    start_cmd = getattr(self.config, "expanded_start_cmd",
                        self.config.start_cmd)
    self.log.info(
      "Launching controller %s: %s" % (self.label, " ".join(start_cmd)))

    launch_in_network_namespace = getattr(self.config,
                                          "launch_in_network_namespace",
                                          False)
    if launch_in_network_namespace:
      (self.process, self.guest_eth_addr, self.host_device) = \
          launch_namespace(
            " ".join(start_cmd),
            self.config.address, self.cid,
            host_ip_addr_str=IPAddressSpace.find_unclaimed_address(
              ip_prefix=self.config.address),
            cwd=self.config.cwd, env=env)
    else:
      self.process = popen_filtered("[%s]" % self.label,
                                    start_cmd, self.config.cwd, env)
    self._register_proc(self.process)
    if self.config.sync:
      self.sync_connection = self.sync_connection_manager.connect(
        self, self.config.sync)
    self._check_snapshot_connect()
    self.state = ControllerState.ALIVE
예제 #27
0
 def unblock_connection(self, connection):
     msg.event("Unblocking connection %s" % connection)
     return connection.io_worker.unblock()
예제 #28
0
 def repair_link(self, link):
     msg.event("Restoring link %s" % str(link))
     if link not in self.network_links:
         raise ValueError("Unknown link %s" % str(link))
     link.start_software_switch.bring_port_up(link.start_port)
     self.cut_links.remove(link)
예제 #29
0
 def crash_switch(self, software_switch):
     msg.event("Crashing software_switch %s" % str(software_switch))
     software_switch.fail()
     self.failed_switches.add(software_switch)
예제 #30
0
 def kill_controller(controller):
   msg.event("Killing controller %s" % str(controller))
   controller.kill()
예제 #31
0
 def unblock_connection(self, connection):
     msg.event("Unblocking connection %s" % connection)
     return connection.io_worker.unblock()
예제 #32
0
 def delay_dp_event(self, dp_event):
     msg.event("Delaying dataplane event")
     # (Monkey patch on a delay counter)
     if not hasattr(dp_event, "delayed_rounds"):
         dp_event.delayed_rounds = 0
     dp_event.delayed_rounds += 1
예제 #33
0
    def simulate(self):
        simulation = self.initialize_simulation()

        # Some implementations send delete flow mods when disconnecting switches; ignore these flow_mods
        if self.ignore_trailing_flow_mod_deletes:
            # switch -> whether we have observed a flow_mod other than a trailing delete yet
            dpid2seen_non_delete = {
                switch.dpid: False
                for switch in simulation.topology.switches
            }

        # Reproduce the routing table state.
        all_flow_mods = []
        for next_event in self.event_list:
            if is_flow_mod(next_event):
                msg.special_event("Injecting %r" % next_event)
                all_flow_mods.append(next_event)
            else:
                msg.openflow_event("Injecting %r" % next_event)
            next_event.manually_inject(simulation)

        # Now filter out all flow_mods that don't correspond to an entry in the
        # final routing table. Do that by walking backwards through the flow_mods,
        # and checking if they match the flow table. If so, add it to list, and
        # remove all flow entries that currently match it to filter overlapping
        # flow_mods from earlier in the event_list.
        relevant_flow_mods = []
        for last_event in reversed(all_flow_mods):
            switch = simulation.topology.get_switch(last_event.dpid)

            # Ignore all trailing flow mod deletes
            if self.ignore_trailing_flow_mod_deletes:
                flow_mod_command = last_event.get_packet().command
                if (not dpid2seen_non_delete[switch.dpid]
                        and (flow_mod_command == OFPFC_DELETE
                             or flow_mod_command == OFPFC_DELETE_STRICT)):
                    continue
                else:
                    dpid2seen_non_delete[switch.dpid] = True

            if switch.table.matching_entries(
                    last_event.get_packet().match) != []:
                relevant_flow_mods.append(last_event)
                switch.table.remove_matching_entries(
                    last_event.get_packet().match)

        relevant_flow_mods.reverse()

        # Print filtered flow mods
        print "\n"
        msg.event("Filtered flow mods:")
        for next_event in relevant_flow_mods:
            print "%r" % next_event
        print "\n"

        # Add back removed entries.
        for flow_mod_event in relevant_flow_mods:
            flow_mod_event.manually_inject(simulation)

        # Now print flow tables of each switch.
        msg.event("Flow tables:")
        for switch in simulation.topology.switches:
            print "Switch %s" % switch.dpid
            switch.show_flow_table()

        return simulation
예제 #34
0
파일: fuzzer.py 프로젝트: NetSys/sts
    def loop(self):
        if self.steps:
            end_time = self.logical_time + self.steps
        else:
            end_time = sys.maxint

        self.interrupted = False
        old_interrupt = None

        def interrupt(sgn, frame):
            msg.interactive("Interrupting fuzzer, dropping to console (press ^C again to terminate)")
            signal.signal(signal.SIGINT, self.old_interrupt)
            self.old_interrupt = None
            self.interrupted = True
            raise KeyboardInterrupt()

        self.old_interrupt = signal.signal(signal.SIGINT, interrupt)

        try:
            # Always connect to controllers explicitly
            self.simulation.connect_to_controllers()
            self._log_input_event(ConnectToControllers())

            if self.delay_startup:
                # Wait until the first OpenFlow message is received
                log.info("Waiting until first OpenfFlow message received..")
                while self.simulation.god_scheduler.pending_receives() == []:
                    self.simulation.io_master.select(self.delay)

            sent_self_packets = False

            while self.logical_time < end_time:
                self.logical_time += 1
                try:
                    if not self._initializing():
                        self.trigger_events()
                        halt = self.maybe_check_invariant()
                        if halt:
                            self.simulation.set_exit_code(5)
                            break
                        self.maybe_inject_trace_event()
                    else:  # Initializing
                        self.check_pending_messages(pass_through=True)
                        if not sent_self_packets and (self.logical_time % self._all_to_all_interval) == 0:
                            # Only need to send self packets once
                            self._send_initialization_packets(self_pkts=True)
                            sent_self_packets = True
                        elif self.logical_time > self.initialization_rounds:
                            # All-to-all mode
                            if (self.logical_time % self._all_to_all_interval) == 0:
                                self._send_initialization_packets(self_pkts=False)
                                self._all_to_all_iterations += 1
                                if self._all_to_all_iterations > len(self.simulation.topology.hosts):
                                    log.info("Done initializing")
                                    self._pending_all_to_all = False
                        self.check_dataplane(pass_through=True)

                    msg.event("Round %d completed." % self.logical_time)
                    time.sleep(self.delay)
                except KeyboardInterrupt as e:
                    if self.interrupted:
                        interactive = Interactive(self.simulation_cfg, self._input_logger)
                        interactive.simulate(self.simulation, bound_objects=(("fuzzer", self),))
                        self.old_interrupt = signal.signal(signal.SIGINT, interrupt)
                    else:
                        raise e

            log.info("Terminating fuzzing after %d rounds" % self.logical_time)
            if self.print_buffers:
                self._print_buffers()

        finally:
            if self.old_interrupt:
                signal.signal(signal.SIGINT, self.old_interrupt)
            if self._input_logger is not None:
                self._input_logger.close(self, self.simulation_cfg)

        return self.simulation