示例#1
0
文件: replayer.py 项目: ZhiLiu/sts
  def decide_drop(self, dp_event):
    ''' Returns True if this event should be dropped, False otherwise '''
    # dp_event is a DpPacketOut object
    # TODO(cs): should have a sanity check in here somewhere to make sure
    # we're still dropping the right number of packets. Test on a high drop
    # rate fuzzer_params
    dp_fingerprint = (DPFingerprint.from_pkt(dp_event.packet),
                      dp_event.node.dpid, dp_event.port.port_no)

    # Skip over the class name (first element of the tuple)
    event_fingerprint = find(lambda f: f[1:] == dp_fingerprint,
                             self.current_dp_fingerprints)
    if event_fingerprint is None:
      # Default to permit if we didn't expect this dp event
      return False
    # Flush this event from both our current window and our events list, so
    # that we don't accidentally conflate distinct dp_events with the same
    # fingerprint
    self.current_dp_fingerprints.remove(event_fingerprint)
    event_idx = self.fingerprint_2_event_idx[event_fingerprint]
    self.events.pop(event_idx)
    # First element of the tuple is the Event class name
    if event_fingerprint[0] == "DataplanePermit":
      return False
    self.stats.record_drop(event_fingerprint)
    return True # DataplaneDrop
示例#2
0
    def decide_drop(self, dp_event):
        ''' Returns True if this event should be dropped, False otherwise '''
        # dp_event is a DpPacketOut object
        # TODO(cs): should have a sanity check in here somewhere to make sure
        # we're still dropping the right number of packets. Test on a high drop
        # rate fuzzer_params
        dp_fingerprint = (DPFingerprint.from_pkt(dp_event.packet),
                          dp_event.node.dpid, dp_event.port.port_no)

        # Skip over the class name (first element of the tuple)
        event_fingerprint = find(lambda f: f[1:] == dp_fingerprint,
                                 self.current_dp_fingerprints)
        if event_fingerprint is None:
            # Default to permit if we didn't expect this dp event
            return False
        # Flush this event from both our current window and our events list, so
        # that we don't accidentally conflate distinct dp_events with the same
        # fingerprint
        self.current_dp_fingerprints.remove(event_fingerprint)
        event_idx = self.fingerprint_2_event_idx[event_fingerprint].pop()
        self.events.pop(event_idx)
        # First element of the tuple is the Event class name
        if event_fingerprint[0] == "DataplanePermit":
            return False
        self.stats.record_drop(event_fingerprint)
        return True  # DataplaneDrop
示例#3
0
  def get_demuxer_for_server_info(self, server_info):
    '''
    server_info is the address of the controller, either a tuple
    (address, port) or a path to a unix domain socket

    Raises a ValueError if there is no SocketDemultiplexer associated
    with the given server_info.
    '''
    demuxer = find(lambda d: d.server_info == server_info, self.demuxers)
    if demuxer is None:
      return ValueError("server_info %s does not have a demuxer" % server_info)
    return demuxer
示例#4
0
  def get_demuxer_for_server_info(self, server_info):
    '''
    server_info is the address of the controller, either a tuple
    (address, port) or a path to a unix domain socket

    Raises a ValueError if there is no SocketDemultiplexer associated
    with the given server_info.
    '''
    demuxer = find(lambda d: d.server_info == server_info, self.demuxers)
    if demuxer is None:
      return ValueError("server_info %s does not have a demuxer" % server_info)
    return demuxer
示例#5
0
 def migrate_host(self, hid, dpid):
     topology = self.simulation.topology
     host = topology.get_host(hid)
     # TODO(cs): make this lookup more efficient
     access_link = find(lambda a: a.host == host, topology.access_links)
     old_ingress_dpid = access_link.switch.dpid
     old_ingress_port_no = access_link.switch_port.port_no
     new_switch = topology.get_switch(dpid)
     new_port_no = max(new_switch.ports.keys()) + 1
     self._log_input_event(
         HostMigration(old_ingress_dpid, old_ingress_port_no, dpid, new_port_no, access_link.host.hid)
     )
     self.simulation.topology.migrate_host(old_ingress_dpid, old_ingress_port_no, dpid, new_port_no)
     self._send_initialization_packet(access_link.host, send_to_self=True)
示例#6
0
 def migrate_host(self, hid, dpid):
   topology = self.simulation.topology
   host = topology.get_host(hid)
   # TODO(cs): make this lookup more efficient
   access_link = find(lambda a: a.host == host, topology.access_links)
   old_ingress_dpid = access_link.switch.dpid
   old_ingress_port_no = access_link.switch_port.port_no
   new_switch = topology.get_switch(dpid)
   new_port_no = max(new_switch.ports.keys()) + 1
   self.simulation.topology.migrate_host(old_ingress_dpid,
                                         old_ingress_port_no,
                                         dpid,
                                         new_port_no)
   self._log_input_event(HostMigration(old_ingress_dpid,
                                       old_ingress_port_no,
                                       dpid,
                                       new_port_no,
                                       access_link.host.hid))
   self._send_initialization_packet(access_link.host, send_to_self=True)
示例#7
0
def find_git_dir(results_dir):
  return find(lambda f: os.path.exists(os.path.join(f, ".git" )), walk_dirs_up(results_dir))
示例#8
0
  def peek(self, dag):
    '''
    If dag.events == [], returns immediately.

    If dag.events != [], assumes that isinstance(dag.events[0], ConnectToControllers)
    '''
    if dag.input_events == []:
      return dag
    # post: len(dag.input_events) > 0

    unsupported_types = [ProcessFlowMod, FailFlowMod, DataplaneDrop]
    if find(lambda e: type(e) in unsupported_types, dag.events) is not None:
      raise ValueError('''Delayed flow_mods not yet supported. Please '''
                       '''implement the TODO near the sleep() call in play_forward()''')

    if not isinstance(dag.events[0], ConnectToControllers):
      raise ValueError("First event must be ConnectToControllers")

    simulation = None
    try:
      # Inferred events includes input events and internal events
      inferred_events = []

      (simulation, controller) = self.setup_simulation()

      # dag.input_events returns only prunable input events. We also need
      # include ConnectToControllers, which is a non-prunable input event.
      assert(dag.input_events[0] != dag.events[0])
      snapshot_inputs = [dag.events[0]] + dag.input_events

      # The input event from the previous iteration, followed by the internal
      # events that were inferred from the previous peek().
      # Since we assume that the first event is always ConnectToControllers,
      # there are never internal events (nor input events) preceding the
      # initial ConnectToControllers.
      # TODO(cs): might not want to contrain the caller's dag in this way.
      events_inferred_last_iteration = []

      for inject_input_idx in xrange(0, len(snapshot_inputs)):
        inject_input = get_inject_input(inject_input_idx, snapshot_inputs)
        following_input = get_following_input(inject_input_idx, snapshot_inputs)
        expected_internal_events = \
           get_expected_internal_events(inject_input, following_input, dag.events)

        log.debug("peek()'ing after input %d (%s)" %
                  (inject_input_idx, str(inject_input)))

        inferred_events += events_inferred_last_iteration

        if expected_internal_events == []:
          # Optimization: if no internal events occured between this input and the
          # next, no need to peek(), just replay the next input
          log.debug("Optimization: no expected internal events")
          Peeker.ambiguous_counts[0.0] += 1
          events_inferred_last_iteration = [inject_input]
          continue

        # We replay events_inferred_last_iteration (internal events preceding
        # inject_input), as well as a NOPInput with the same timestamp as inject_input
        # to ensure that the timing is the same before peek()ing.
        fencepost = NOPInput(time=inject_input.time, round=inject_input.round)
        dag_interval = EventDag(events_inferred_last_iteration + [fencepost])
        wait_time_seconds = self.get_wait_time_seconds(inject_input, following_input)
        found_events = self.find_internal_events(simulation, controller,
                                                 dag_interval, inject_input,
                                                 wait_time_seconds)
        events_inferred_last_iteration = [inject_input]
        events_inferred_last_iteration += match_and_filter(found_events, expected_internal_events)

      # Don't forget the final iteration's output
      inferred_events += events_inferred_last_iteration
    finally:
      if simulation is not None:
        simulation.clean_up()

    return EventDag(inferred_events)
示例#9
0
def setup_experiment(args, config):
  # Grab parameters
  if args.exp_name:
    config.exp_name = args.exp_name
  elif not hasattr(config, 'exp_name'):
    config.exp_name = exp_lifecycle.guess_config_name(config)

  if not hasattr(config, 'results_dir'):
    config.results_dir = "experiments/%s" % config.exp_name

  if args.timestamp_results is not None:
    # Note that argparse returns a list
    config.timestamp_results = args.timestamp_results

  if hasattr(config, 'timestamp_results') and config.timestamp_results:
    now = timestamp_string()
    config.results_dir += "_" + str(now)

  # Set up results directory
  create_python_dir("./experiments")
  create_clean_python_dir(config.results_dir)

  # Copy stdout and stderr to a file "simulator.out"
  tee = Tee(open(os.path.join(config.results_dir, "simulator.out"), "w"))
  tee.tee_stdout()
  tee.tee_stderr()

  # Load log configuration.
  # N.B. this must be done after Tee()'ing.
  if args.log_config:
    logging.config.fileConfig(args.log_config)
  else:
    logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO)

  # If specified, set up a config file for each controller
  for controller_config in config.simulation_config.controller_configs:
    if controller_config.config_template:
      controller_config.generate_config_file(config.results_dir)

  # Make sure that there are no uncommited changes
  if args.publish:
    exp_lifecycle.publish_prepare(config.exp_name, config.results_dir)

  # Record machine information for this experiment
  additional_metadata = None
  if hasattr(config, "get_additional_metadata"):
    additional_metadata = config.get_additional_metadata()

  exp_lifecycle.dump_metadata("%s/metadata" % config.results_dir,
                              additional_metadata=additional_metadata)

  # Copy over config file
  config_file = re.sub(r'\.pyc$', '.py', config.__file__)
  if os.path.exists(config_file):
    canonical_config_file = config.results_dir + "/orig_config.py"
    if os.path.abspath(config_file) != os.path.abspath(canonical_config_file):
      shutil.copy(config_file, canonical_config_file)

  # Check configuration warnings
  log = logging.getLogger("setup")

  con = config.control_flow.simulation_cfg.controller_configs

  def builtin_pox_controller(c):
    # pox/ is already accounted for in metadata.
    return ("POXController" in str(c.controller_class) and
            c.cwd is not None and
            re.match("^pox[/]?", c.cwd) is not None)

  if (not hasattr(config, "get_additional_metadata") and
      find(lambda c: not builtin_pox_controller(c),
           config.control_flow.simulation_cfg.controller_configs) is not None):
    log.warn('''No get_additional_metadata() defined for config file. See '''
             '''config/nox_routing.py for an example.''')
示例#10
0
  def peek(self, dag):
    '''
    If dag.events == [], returns immediately.

    If dag.events != [], assumes that isinstance(dag.events[0], ConnectToControllers)
    '''
    if dag.input_events == []:
      return dag
    # post: len(dag.input_events) > 0

    unsupported_types = [ProcessFlowMod, DataplaneDrop]
    if find(lambda e: type(e) in unsupported_types, dag.events) is not None:
      raise ValueError('''Delayed flow_mods not yet supported. Please '''
                       '''implement the TODO near the sleep() call in play_forward()''')

    if not isinstance(dag.events[0], ConnectToControllers):
      raise ValueError("First event must be ConnectToControllers")

    simulation = None
    try:
      # Inferred events includes input events and internal events
      inferred_events = []

      (simulation, controller) = self.setup_simulation()

      # dag.input_events returns only prunable input events. We also need
      # include ConnectToControllers, which is a non-prunable input event.
      assert(dag.input_events[0] != dag.events[0])
      snapshot_inputs = [dag.events[0]] + dag.input_events

      # The input event from the previous iteration, followed by the internal
      # events that were inferred from the previous peek().
      # Since we assume that the first event is always ConnectToControllers,
      # there are never internal events (nor input events) preceding the
      # initial ConnectToControllers.
      # TODO(cs): might not want to contrain the caller's dag in this way.
      events_inferred_last_iteration = []

      for inject_input_idx in xrange(0, len(snapshot_inputs)):
        inject_input = get_inject_input(inject_input_idx, snapshot_inputs)
        following_input = get_following_input(inject_input_idx, snapshot_inputs)
        expected_internal_events = \
           get_expected_internal_events(inject_input, following_input, dag.events)

        log.debug("peek()'ing after input %d (%s)" %
                  (inject_input_idx, str(inject_input)))

        inferred_events += events_inferred_last_iteration

        # We replay events_inferred_last_iteration (internal events preceding
        # inject_input), as well as a NOPInput with the same timestamp as inject_input
        # to ensure that the timing is the same before peek()ing.
        fencepost = NOPInput(time=inject_input.time, round=inject_input.round)
        dag_interval = EventDag(events_inferred_last_iteration + [fencepost])

        if expected_internal_events == []:
          # Optimization: if no internal events occured between this input and the
          # next, no need to peek(), just bring the simulation's state forward up to
          # inject_input
          log.debug("Optimization: no expected internal events")
          Peeker.ambiguous_counts[0.0] += 1
          self.replay_interval(simulation, dag_interval, 0)
          events_inferred_last_iteration = [inject_input]
          continue

        wait_time_seconds = self.get_wait_time_seconds(inject_input, following_input)
        (found_events, snapshotter) = self.find_internal_events(simulation, controller,
                                                                dag_interval, inject_input,
                                                                wait_time_seconds)
        events_inferred_last_iteration = [inject_input]
        events_inferred_last_iteration += match_and_filter(found_events, expected_internal_events)
        snapshotter.snapshot_proceed()

      # Don't forget the final iteration's output
      inferred_events += events_inferred_last_iteration
    finally:
      if simulation is not None:
        simulation.clean_up()

    return EventDag(inferred_events)
示例#11
0
def setup_experiment(args, config):
    # Grab parameters
    if args.exp_name:
        config.exp_name = args.exp_name
    elif not hasattr(config, 'exp_name'):
        config.exp_name = exp_lifecycle.guess_config_name(config)

    if not hasattr(config, 'results_dir'):
        config.results_dir = "experiments/%s" % config.exp_name

    if args.timestamp_results is not None:
        # Note that argparse returns a list
        config.timestamp_results = args.timestamp_results

    if hasattr(config, 'timestamp_results') and config.timestamp_results:
        now = timestamp_string()
        config.results_dir += "_" + str(now)

    # Set up results directory
    create_python_dir("./experiments")
    create_clean_python_dir(config.results_dir)

    # Copy stdout and stderr to a file "simulator.out"
    tee = Tee(open(os.path.join(config.results_dir, "simulator.out"), "w"))
    tee.tee_stdout()
    tee.tee_stderr()

    # Load log configuration.
    # N.B. this must be done after Tee()'ing.
    if args.log_config:
        logging.config.fileConfig(args.log_config)
    else:
        logging.basicConfig(
            level=logging.DEBUG if args.verbose else logging.INFO)

    # If specified, set up a config file for each controller
    for controller_config in config.simulation_config.controller_configs:
        if controller_config.config_template:
            controller_config.generate_config_file(config.results_dir)

    # Make sure that there are no uncommited changes
    if args.publish:
        exp_lifecycle.publish_prepare(config.exp_name, config.results_dir)

    # Record machine information for this experiment
    additional_metadata = None
    if hasattr(config, "get_additional_metadata"):
        additional_metadata = config.get_additional_metadata()

    exp_lifecycle.dump_metadata("%s/metadata" % config.results_dir,
                                additional_metadata=additional_metadata)

    # Copy over config file
    config_file = re.sub(r'\.pyc$', '.py', config.__file__)
    if os.path.exists(config_file):
        canonical_config_file = config.results_dir + "/orig_config.py"
        if os.path.abspath(config_file) != os.path.abspath(
                canonical_config_file):
            shutil.copy(config_file, canonical_config_file)

    # Check configuration warnings
    log = logging.getLogger("setup")

    con = config.control_flow.simulation_cfg.controller_configs

    def builtin_pox_controller(c):
        # pox/ is already accounted for in metadata.
        return ("POXController" in str(c.controller_class)
                and c.cwd is not None
                and re.match("^pox[/]?", c.cwd) is not None)

    if (not hasattr(config, "get_additional_metadata")
            and find(lambda c: not builtin_pox_controller(c),
                     config.control_flow.simulation_cfg.controller_configs)
            is not None):
        log.warn(
            '''No get_additional_metadata() defined for config file. See '''
            '''config/nox_routing.py for an example.''')