Exemple #1
0
  def __init__(self, simulation_cfg, superlog_path_or_dag, mock_controllers=True, input_logger=None,
               show_flow_tables_each_step=True):
    # TODO(cs): allow user to specify a round number where they want to stop,
    # otherwise play forward events without asking for interactive ack.
    Interactive.__init__(self, simulation_cfg, input_logger=input_logger)

    if mock_controllers is False:
      raise NotImplementedError("Live controllers not yet supported")
    self.mock_controllers = mock_controllers

    if type(superlog_path_or_dag) == str:
      superlog_path = superlog_path_or_dag
      # The dag is codefied as a list, where each element has
      # a list of its dependents.
      self.event_list = EventDag(log_parser.parse_path(superlog_path)).events
    else:
      self.event_list = superlog_path_or_dag.events

    # TODO(cs): support compute_interpolated_time whenever we support
    # non-mocked controllers.

    if self.mock_controllers:
      self.event_list = [ e for e in self.event_list
                          if type(e) in InteractiveReplayer.supported_input_events or
                             type(e) in InteractiveReplayer.supported_internal_events ]
    self.show_flow_tables_each_step = show_flow_tables_each_step
    def __init__(self,
                 simulation_cfg,
                 superlog_path_or_dag,
                 mock_controllers=True,
                 input_logger=None,
                 show_flow_tables_each_step=True):
        # TODO(cs): allow user to specify a round number where they want to stop,
        # otherwise play forward events without asking for interactive ack.
        Interactive.__init__(self, simulation_cfg, input_logger=input_logger)

        if mock_controllers is False:
            raise NotImplementedError("Live controllers not yet supported")
        self.mock_controllers = mock_controllers

        if type(superlog_path_or_dag) == str:
            superlog_path = superlog_path_or_dag
            # The dag is codefied as a list, where each element has
            # a list of its dependents.
            self.event_list = EventDag(
                log_parser.parse_path(superlog_path)).events
        else:
            self.event_list = superlog_path_or_dag.events

        # TODO(cs): support compute_interpolated_time whenever we support
        # non-mocked controllers.

        if self.mock_controllers:
            self.event_list = [
                e for e in self.event_list
                if type(e) in InteractiveReplayer.supported_input_events
                or type(e) in InteractiveReplayer.supported_internal_events
            ]
        self.show_flow_tables_each_step = show_flow_tables_each_step
  def _track_new_internal_events(self, simulation, replayer):
    ''' Pre: simulation must have been run through a replay'''
    # We always check against internal events that were buffered at the end of
    # the original run (don't want to overcount)
    prev_buffered_receives = []
    try:
      path = self.superlog_path + ".unacked"
      if not os.path.exists(path):
        log.warn("unacked internal events file from original run does not exist")
        return
      prev_buffered_receives = set([ e.pending_receive for e in
                                     [ f for f in EventDag(log_parser.parse_path(path)).events
                                       if type(f) == ControlMessageReceive ] ])
    except ValueError as e:
      log.warn("unacked internal events is corrupt? %r" % e)
      return
    buffered_message_receipts = []
    for p in simulation.openflow_buffer.pending_receives():
      if p not in prev_buffered_receives:
        buffered_message_receipts.append(repr(p))
      else:
        prev_buffered_receives.remove(p)

    self._runtime_stats.record_buffered_message_receipts(buffered_message_receipts)
    new_internal_events = replayer.unexpected_state_changes + replayer.passed_unexpected_messages
    self._runtime_stats.record_new_internal_events(new_internal_events)
    self._runtime_stats.record_early_internal_events(replayer.early_state_changes)
    self._runtime_stats.record_timed_out_events(dict(replayer.event_scheduler_stats.event2timeouts))
    self._runtime_stats.record_matched_events(dict(replayer.event_scheduler_stats.event2matched))
Exemple #4
0
  def _track_new_internal_events(self, simulation, replayer):
    ''' Pre: simulation must have been run through a replay'''
    # We always check against internal events that were buffered at the end of
    # the original run (don't want to overcount)
    prev_buffered_receives = []
    try:
      path = self.superlog_path + ".unacked"
      if not os.path.exists(path):
        log.warn("unacked internal events file from original run does not exist")
        return
      prev_buffered_receives = set([ e.pending_receive for e in
                                     [ f for f in EventDag(log_parser.parse_path(path)).events
                                       if type(f) == ControlMessageReceive ] ])
    except ValueError as e:
      log.warn("unacked internal events is corrupt? %r" % e)
      return
    buffered_message_receipts = []
    for p in simulation.openflow_buffer.pending_receives:
      if p not in prev_buffered_receives:
        buffered_message_receipts.append(repr(p))
      else:
        prev_buffered_receives.remove(p)

    self._runtime_stats.record_buffered_message_receipts(buffered_message_receipts)
    new_internal_events = replayer.unexpected_state_changes + replayer.passed_unexpected_messages
    self._runtime_stats.record_new_internal_events(new_internal_events)
    self._runtime_stats.record_early_internal_events(replayer.early_state_changes)
    self._runtime_stats.record_timed_out_events(replayer.event_scheduler_stats.get_timeouts_dict())
    self._runtime_stats.record_matched_events(replayer.event_scheduler_stats.get_matches_dict())
Exemple #5
0
 def test_basic(self):
     name = None
     try:
         self.open_simple_superlog()
         events = log_parser.parse_path(self.tmpfile)
         self.assertEqual(2, len(events))
         self.assertEqual(LinkFailure, type(events[0]))
         self.assertEqual(LinkRecovery, type(events[1]))
     finally:
         if name is not None:
             os.unlink(name)
 def test_basic(self):
   name = None
   try:
     self.open_simple_superlog()
     events = log_parser.parse_path(self.tmpfile)
     self.assertEqual(2, len(events))
     self.assertEqual(LinkFailure,type(events[0]))
     self.assertEqual(LinkRecovery,type(events[1]))
   finally:
     if name is not None:
       os.unlink(name)
  def __init__(self, simulation_cfg, superlog_path_or_dag):
    # TODO(cs): allow the user to specify a stop point in the event dag, in
    # case the point they are interested in occurs before the end of the trace.
    self.simulation_cfg = simulation_cfg
    self.sync_callback = ReplaySyncCallback()
    if type(superlog_path_or_dag) == str:
      superlog_path = superlog_path_or_dag
      # The dag is codefied as a list, where each element has
      # a list of its dependents.
      self.event_list = EventDag(log_parser.parse_path(superlog_path)).events
    else:
      self.event_list = superlog_path_or_dag.events

    self.event_list = [ e for e in self.event_list
                        if type(e) == ControlMessageReceive
                        and type(e.get_packet()) != ofp_packet_out ]
Exemple #8
0
    def __init__(self,
                 simulation_cfg,
                 superlog_path_or_dag,
                 ignore_trailing_flow_mod_deletes=True):
        # TODO(cs): allow the user to specify a stop point in the event dag, in
        # case the point they are interested in occurs before the end of the trace.
        self.simulation_cfg = simulation_cfg
        self.sync_callback = ReplaySyncCallback()
        if type(superlog_path_or_dag) == str:
            superlog_path = superlog_path_or_dag
            # The dag is codefied as a list, where each element has
            # a list of its dependents.
            self.event_list = EventDag(
                log_parser.parse_path(superlog_path)).events
        else:
            self.event_list = superlog_path_or_dag.events

        self.event_list = [
            e for e in self.event_list if type(e) == ControlMessageReceive
            and type(e.get_packet()) != ofp_packet_out
        ]
        self.ignore_trailing_flow_mod_deletes = ignore_trailing_flow_mod_deletes
Exemple #9
0
  def __init__(self, simulation_cfg, superlog_path_or_dag, create_event_scheduler=None,
               print_buffers=True, wait_on_deterministic_values=False, default_dp_permit=False,
               fail_to_interactive=False, fail_to_interactive_on_persistent_violations=False,
               end_in_interactive=False, input_logger=None,
               allow_unexpected_messages=False,
               pass_through_whitelisted_messages=True,
               delay_flow_mods=False,
               **kwargs):
    ControlFlow.__init__(self, simulation_cfg)
    if wait_on_deterministic_values:
      self.sync_callback = ReplaySyncCallback()
    else:
      self.sync_callback = ReplaySyncCallback(self.get_interpolated_time)

    if type(superlog_path_or_dag) == str:
      superlog_path = superlog_path_or_dag
      # The dag is codefied as a list, where each element has
      # a list of its dependents
      self.dag = EventDag(log_parser.parse_path(superlog_path))
    else:
      self.dag = superlog_path_or_dag

    if len(self.dag.events) == 0:
      raise ValueError("No events to replay!")

    self.default_dp_permit = default_dp_permit
    # Set DataplanePermit and DataplaneDrop to passive if permit is set
    # to default
    for event in [ e for e in self.dag.events if type(e) in dp_events ]:
      event.passive = default_dp_permit

    self.dp_checker = None
    if default_dp_permit:
      self.dp_checker = DataplaneChecker(self.dag)

    self.print_buffers_flag = print_buffers

    # compute interpolate to time to be just before first event
    self.compute_interpolated_time(self.dag.events[0])
    # String repesentations of unexpected state changes we've passed through, for
    # statistics purposes.
    self.unexpected_state_changes = []
    self.early_state_changes = []
    self.event_scheduler_stats = None
    self.end_in_interactive = end_in_interactive
    self.fail_to_interactive = fail_to_interactive
    self.fail_to_interactive_on_persistent_violations =\
      fail_to_interactive_on_persistent_violations
    self._input_logger = input_logger
    self.allow_unexpected_messages = allow_unexpected_messages
    self.pass_through_whitelisted_messages = pass_through_whitelisted_messages
    # How many logical rounds to peek ahead when deciding if a message is
    # expected or not.
    self.expected_message_round_window = 3
    # String repesentations of unexpected messages we've passed through, for
    # statistics purposes.
    self.passed_unexpected_messages = []
    self.delay_flow_mods = delay_flow_mods

    if self.pass_through_whitelisted_messages:
      for event in self.dag.events:
        if hasattr(event, "ignore_whitelisted_packets"):
          event.ignore_whitelisted_packets = True

    if create_event_scheduler:
      self.create_event_scheduler = create_event_scheduler
    else:
      self.create_event_scheduler = \
        lambda simulation: EventScheduler(simulation,
            **{ k: v for k,v in kwargs.items()
                if k in EventScheduler.kwargs })
Exemple #10
0
    def __init__(self,
                 simulation_cfg,
                 superlog_path_or_dag,
                 create_event_scheduler=None,
                 print_buffers=True,
                 wait_on_deterministic_values=False,
                 default_dp_permit=False,
                 fail_to_interactive=False,
                 fail_to_interactive_on_persistent_violations=False,
                 end_in_interactive=False,
                 input_logger=None,
                 allow_unexpected_messages=False,
                 expected_message_round_window=3,
                 pass_through_whitelisted_messages=False,
                 delay_flow_mods=False,
                 invariant_check_name="",
                 bug_signature="",
                 end_wait_seconds=0.5,
                 transform_dag=None,
                 pass_through_sends=False,
                 fail_fast=False,
                 check_interval=5,
                 **kwargs):
        '''
     - If invariant_check_name is not None, check it at the end for the
       execution
     - If bug_signature is not None, check whether this particular signature
       appears in the output of the invariant check at the end of the
       execution
    '''
        ControlFlow.__init__(self, simulation_cfg)
        # Label uniquely identifying this replay, set in init_results()
        self.replay_id = "N/A"
        self.logical_time = 0
        if wait_on_deterministic_values:
            self.sync_callback = ReplaySyncCallback()
        else:
            self.sync_callback = ReplaySyncCallback(self.get_interpolated_time)

        if type(superlog_path_or_dag) == str:
            superlog_path = superlog_path_or_dag
            # The dag is codefied as a list, where each element has
            # a list of its dependents
            self.dag = EventDag(log_parser.parse_path(superlog_path))
        else:
            self.dag = superlog_path_or_dag

        if len(self.dag.events) == 0:
            raise ValueError("No events to replay!")

        self.default_dp_permit = default_dp_permit
        self.dp_checker = self._setup_dp_checker(default_dp_permit)
        if self.default_dp_permit:
            # Set DataplanePermit and DataplaneDrop to passive if permit is set
            # to default
            # TODO(cs): rather than setting these to passive (which still causes them to
            # be scheduled as regular events) should these just be removed from the
            # event dag altogether?
            for event in [e for e in self.dag.events if type(e) in dp_events]:
                event.passive = default_dp_permit

        self.print_buffers_flag = print_buffers
        self.fail_fast = fail_fast
        self.check_interval = check_interval

        # compute interpolate to time to be just before first event
        self.compute_interpolated_time(self.dag.events[0])
        # String repesentations of unexpected state changes we've passed through, for
        # statistics purposes.
        self.unexpected_state_changes = []
        self.early_state_changes = []
        self.event_scheduler_stats = None
        self.end_in_interactive = end_in_interactive
        self.fail_to_interactive = fail_to_interactive
        self.fail_to_interactive_on_persistent_violations =\
          fail_to_interactive_on_persistent_violations
        self._input_logger = input_logger
        self.allow_unexpected_messages = allow_unexpected_messages
        self.expected_message_round_window = expected_message_round_window
        self.pass_through_whitelisted_messages = pass_through_whitelisted_messages
        self.pass_through_sends = pass_through_sends
        # How many logical rounds to peek ahead when deciding if a message is
        # expected or not.
        # String repesentations of unexpected messages we've passed through, for
        # statistics purposes.
        self.passed_unexpected_messages = []
        self.delay_flow_mods = delay_flow_mods
        self.end_wait_seconds = end_wait_seconds
        self.transform_dag = transform_dag
        self.bug_signature = bug_signature
        self.invariant_check_name = invariant_check_name
        self.invariant_check = None
        if self.invariant_check_name:
            if self.invariant_check_name not in name_to_invariant_check:
                raise ValueError(
                    '''Unknown invariant check %s.\n'''
                    '''Invariant check name must be defined in config.invariant_checks''',
                    self.invariant_check_name)
            self.invariant_check = name_to_invariant_check[
                self.invariant_check_name]

        if self.pass_through_whitelisted_messages:
            for event in self.dag.events:
                if hasattr(event, "ignore_whitelisted_packets"):
                    event.ignore_whitelisted_packets = True

        if self.simulation_cfg.ignore_interposition:
            self._ignore_interposition()

        if create_event_scheduler:
            self.create_event_scheduler = create_event_scheduler
        else:
            if self.default_dp_permit:
                # Tell EventScheduler to use call into us whenever it wants to sleep or
                # select, so that we can keep forwarding dataplane packets.
                kwargs[
                    'sleep_continuation'] = self._sleep_with_dataplane_passthrough
                kwargs[
                    'select_continuation'] = self._select_with_dataplane_passthrough

            self.create_event_scheduler = \
              lambda simulation: EventScheduler(simulation,
                  **{ k: v for k,v in kwargs.items()
                      if k in EventScheduler.kwargs })

        unknown_kwargs = [
            k for k in kwargs.keys() if k not in EventScheduler.kwargs
        ]
        if unknown_kwargs != []:
            raise ValueError("Unknown kwargs %s" % str(unknown_kwargs))
Exemple #11
0
    def __init__(self,
                 simulation_cfg,
                 superlog_path_or_dag,
                 invariant_check_name=None,
                 transform_dag=None,
                 end_wait_seconds=0.5,
                 mcs_trace_path=None,
                 extra_log=None,
                 runtime_stats_path=None,
                 wait_on_deterministic_values=False,
                 no_violation_verification_runs=1,
                 optimized_filtering=False,
                 forker=LocalForker(),
                 replay_final_trace=True,
                 strict_assertion_checking=False,
                 delay_flow_mods=False,
                 **kwargs):
        super(MCSFinder, self).__init__(simulation_cfg)
        # number of subsequences delta debugging has examined so far, for
        # distingushing runtime stats from different intermediate runs.
        self.subsequence_id = 0
        self.mcs_log_tracker = None
        self.replay_log_tracker = None
        self.mcs_trace_path = mcs_trace_path
        self.sync_callback = None
        self._log = logging.getLogger("mcs_finder")

        if invariant_check_name is None:
            raise ValueError("Must specify invariant check")
        if invariant_check_name not in name_to_invariant_check:
            raise ValueError(
                '''Unknown invariant check %s.\n'''
                '''Invariant check name must be defined in config.invariant_checks''',
                invariant_check_name)
        self.invariant_check = name_to_invariant_check[invariant_check_name]

        if type(superlog_path_or_dag) == str:
            self.superlog_path = superlog_path_or_dag
            # The dag is codefied as a list, where each element has
            # a list of its dependents
            self.dag = EventDag(log_parser.parse_path(self.superlog_path))
        else:
            self.dag = superlog_path_or_dag

        last_invariant_violation = self.dag.get_last_invariant_violation()
        if last_invariant_violation is None:
            raise ValueError("No invariant violation found in dag...")
        violations = last_invariant_violation.violations
        if len(violations) > 1:
            self.bug_signature = None
            while self.bug_signature is None:
                msg.interactive(
                    "\n------------------------------------------\n")
                msg.interactive(
                    "Multiple violations detected! Choose one for MCS Finding:"
                )
                for i, violation in enumerate(violations):
                    msg.interactive("  [%d] %s" % (i + 1, violation))
                violation_index = msg.raw_input("> ")
                if re.match("^\d+$", violation_index) is None or\
                   int(violation_index) < 1 or\
                   int(violation_index) > len(violations):
                    msg.fail("Must provide an integer between 1 and %d!" %
                             len(violations))
                    continue
                self.bug_signature = violations[int(violation_index) - 1]
        else:
            self.bug_signature = violations[0]
        msg.success(
            "\nBug signature to match is %s. Proceeding with MCS finding!\n" %
            self.bug_signature)

        self.transform_dag = transform_dag
        # A second log with just our MCS progress log messages
        self._extra_log = extra_log
        self.kwargs = kwargs
        self.end_wait_seconds = end_wait_seconds
        self.wait_on_deterministic_values = wait_on_deterministic_values
        # `no' means "number"
        self.no_violation_verification_runs = no_violation_verification_runs
        self._runtime_stats = RuntimeStats(
            self.subsequence_id, runtime_stats_path=runtime_stats_path)
        # Whether to try alternate trace splitting techiques besides splitting by time.
        self.optimized_filtering = optimized_filtering
        self.forker = forker
        self.replay_final_trace = replay_final_trace
        self.strict_assertion_checking = strict_assertion_checking
        self.delay_flow_mods = delay_flow_mods
  def __init__(self, simulation_cfg, superlog_path_or_dag,
               invariant_check_name=None,
               transform_dag=None, end_wait_seconds=0.5,
               mcs_trace_path=None, extra_log=None, runtime_stats_path=None,
               wait_on_deterministic_values=False,
               no_violation_verification_runs=1,
               optimized_filtering=False, forker=LocalForker(),
               replay_final_trace=True, strict_assertion_checking=False,
               **kwargs):
    super(MCSFinder, self).__init__(simulation_cfg)
    # number of subsequences delta debugging has examined so far, for
    # distingushing runtime stats from different intermediate runs.
    self.subsequence_id = 0
    self.mcs_log_tracker = None
    self.replay_log_tracker = None
    self.mcs_trace_path = mcs_trace_path
    self.sync_callback = None
    self._log = logging.getLogger("mcs_finder")

    if invariant_check_name is None:
      raise ValueError("Must specify invariant check")
    if invariant_check_name not in name_to_invariant_check:
      raise ValueError('''Unknown invariant check %s.\n'''
                       '''Invariant check name must be defined in config.invariant_checks''',
                       invariant_check_name)
    self.invariant_check = name_to_invariant_check[invariant_check_name]

    if type(superlog_path_or_dag) == str:
      self.superlog_path = superlog_path_or_dag
      # The dag is codefied as a list, where each element has
      # a list of its dependents
      self.dag = EventDag(log_parser.parse_path(self.superlog_path))
    else:
      self.dag = superlog_path_or_dag

    last_invariant_violation = self.dag.get_last_invariant_violation()
    if last_invariant_violation is None:
      raise ValueError("No invariant violation found in dag...")
    violations = last_invariant_violation.violations
    if len(violations) > 1:
      self.bug_signature = None
      while self.bug_signature is None:
        msg.interactive("\n------------------------------------------\n")
        msg.interactive("Multiple violations detected! Choose one for MCS Finding:")
        for i, violation in enumerate(violations):
          msg.interactive("  [%d] %s" % (i+1, violation))
        violation_index = msg.raw_input("> ")
        if re.match("^\d+$", violation_index) is None or\
           int(violation_index) < 1 or\
           int(violation_index) > len(violations):
          msg.fail("Must provide an integer between 1 and %d!" % len(violations))
          continue
        self.bug_signature = violations[int(violation_index)-1]
    else:
      self.bug_signature = violations[0]
    msg.success("\nBug signature to match is %s. Proceeding with MCS finding!\n" % self.bug_signature)

    self.transform_dag = transform_dag
    # A second log with just our MCS progress log messages
    self._extra_log = extra_log
    self.kwargs = kwargs
    self.end_wait_seconds = end_wait_seconds
    self.wait_on_deterministic_values = wait_on_deterministic_values
    # `no' means "number"
    self.no_violation_verification_runs = no_violation_verification_runs
    self._runtime_stats = RuntimeStats(self.subsequence_id, runtime_stats_path=runtime_stats_path)
    # Whether to try alternate trace splitting techiques besides splitting by time.
    self.optimized_filtering = optimized_filtering
    self.forker = forker
    self.replay_final_trace = replay_final_trace
    self.strict_assertion_checking = strict_assertion_checking
Exemple #13
0
  def __init__(self, simulation_cfg, superlog_path_or_dag, create_event_scheduler=None,
               print_buffers=True, wait_on_deterministic_values=False, default_dp_permit=False,
               fail_to_interactive=False, fail_to_interactive_on_persistent_violations=False,
               end_in_interactive=False, input_logger=None,
               allow_unexpected_messages=False,
               expected_message_round_window=3,
               pass_through_whitelisted_messages=False,
               delay_flow_mods=False, invariant_check_name="",
               bug_signature="", end_wait_seconds=0.5,
               transform_dag=None, pass_through_sends=False,
               fail_fast=False, check_interval=5,
               **kwargs):
    '''
     - If invariant_check_name is not None, check it at the end for the
       execution
     - If bug_signature is not None, check whether this particular signature
       appears in the output of the invariant check at the end of the
       execution
    '''
    ControlFlow.__init__(self, simulation_cfg)
    # Label uniquely identifying this replay, set in init_results()
    self.replay_id = "N/A"
    self.logical_time = 0
    if wait_on_deterministic_values:
      self.sync_callback = ReplaySyncCallback()
    else:
      self.sync_callback = ReplaySyncCallback(self.get_interpolated_time)

    if type(superlog_path_or_dag) == str:
      superlog_path = superlog_path_or_dag
      # The dag is codefied as a list, where each element has
      # a list of its dependents
      self.dag = EventDag(log_parser.parse_path(superlog_path))
    else:
      self.dag = superlog_path_or_dag

    if len(self.dag.events) == 0:
      raise ValueError("No events to replay!")

    self.default_dp_permit = default_dp_permit
    self.dp_checker = self._setup_dp_checker(default_dp_permit)
    if self.default_dp_permit:
      # Set DataplanePermit and DataplaneDrop to passive if permit is set
      # to default
      # TODO(cs): rather than setting these to passive (which still causes them to
      # be scheduled as regular events) should these just be removed from the
      # event dag altogether?
      for event in [ e for e in self.dag.events if type(e) in dp_events ]:
        event.passive = default_dp_permit

    self.print_buffers_flag = print_buffers
    self.fail_fast = fail_fast
    self.check_interval = check_interval

    # compute interpolate to time to be just before first event
    self.compute_interpolated_time(self.dag.events[0])
    # String repesentations of unexpected state changes we've passed through, for
    # statistics purposes.
    self.unexpected_state_changes = []
    self.early_state_changes = []
    self.event_scheduler_stats = None
    self.end_in_interactive = end_in_interactive
    self.fail_to_interactive = fail_to_interactive
    self.fail_to_interactive_on_persistent_violations =\
      fail_to_interactive_on_persistent_violations
    self._input_logger = input_logger
    self.allow_unexpected_messages = allow_unexpected_messages
    self.expected_message_round_window = expected_message_round_window
    self.pass_through_whitelisted_messages = pass_through_whitelisted_messages
    self.pass_through_sends = pass_through_sends
    # How many logical rounds to peek ahead when deciding if a message is
    # expected or not.
    # String repesentations of unexpected messages we've passed through, for
    # statistics purposes.
    self.passed_unexpected_messages = []
    self.delay_flow_mods = delay_flow_mods
    self.end_wait_seconds = end_wait_seconds
    self.transform_dag = transform_dag
    self.bug_signature = bug_signature
    self.invariant_check_name = invariant_check_name
    self.invariant_check = None
    if self.invariant_check_name:
      if self.invariant_check_name not in name_to_invariant_check:
        raise ValueError('''Unknown invariant check %s.\n'''
                         '''Invariant check name must be defined in config.invariant_checks''',
                         self.invariant_check_name)
      self.invariant_check = name_to_invariant_check[self.invariant_check_name]

    if self.pass_through_whitelisted_messages:
      for event in self.dag.events:
        if hasattr(event, "ignore_whitelisted_packets"):
          event.ignore_whitelisted_packets = True

    if self.simulation_cfg.ignore_interposition:
      self._ignore_interposition()

    if create_event_scheduler:
      self.create_event_scheduler = create_event_scheduler
    else:
      if self.default_dp_permit:
        # Tell EventScheduler to use call into us whenever it wants to sleep or
        # select, so that we can keep forwarding dataplane packets.
        kwargs['sleep_continuation'] = self._sleep_with_dataplane_passthrough
        kwargs['select_continuation'] = self._select_with_dataplane_passthrough

      self.create_event_scheduler = \
        lambda simulation: EventScheduler(simulation,
            **{ k: v for k,v in kwargs.items()
                if k in EventScheduler.kwargs })

    unknown_kwargs = [ k for k in kwargs.keys() if k not in EventScheduler.kwargs ]
    if unknown_kwargs != []:
      raise ValueError("Unknown kwargs %s" % str(unknown_kwargs))
Exemple #14
0
  def __init__(self, simulation_cfg, superlog_path_or_dag,
               invariant_check_name="", bug_signature="", transform_dag=None,
               mcs_trace_path=None, extra_log=None, runtime_stats_path=None,
               max_replays_per_subsequence=1,
               optimized_filtering=False, forker=LocalForker(),
               replay_final_trace=True, strict_assertion_checking=False,
               no_violation_verification_runs=None,
               **kwargs):
    ''' Note that you may pass in any keyword argument for Replayer to
    MCSFinder, except 'bug_signature' and 'invariant_check_name' '''
    super(MCSFinder, self).__init__(simulation_cfg)
    # number of subsequences delta debugging has examined so far, for
    # distingushing runtime stats from different intermediate runs.
    self.subsequence_id = 0
    self.mcs_log_tracker = None
    self.replay_log_tracker = None
    self.mcs_trace_path = mcs_trace_path
    self.sync_callback = None
    self._log = logging.getLogger("mcs_finder")

    if invariant_check_name == "":
      raise ValueError("Must specify invariant check")
    if invariant_check_name not in name_to_invariant_check:
      raise ValueError('''Unknown invariant check %s.\n'''
                       '''Invariant check name must be defined in config.invariant_checks''',
                       invariant_check_name)
    self.invariant_check_name = invariant_check_name
    self.invariant_check = name_to_invariant_check[invariant_check_name]

    if type(superlog_path_or_dag) == str:
      self.superlog_path = superlog_path_or_dag
      # The dag is codefied as a list, where each element has
      # a list of its dependents
      self.dag = EventDag(log_parser.parse_path(self.superlog_path))
    else:
      self.dag = superlog_path_or_dag

    if self.simulation_cfg.ignore_interposition:
      filtered_events = [e for e in self.dag.events if type(e) not in all_internal_events]
      self.dag = EventDag(filtered_events)

    last_invariant_violation = self.dag.get_last_invariant_violation()
    if last_invariant_violation is None:
      raise ValueError("No invariant violation found in dag...")
    violations = last_invariant_violation.violations
    self.bug_signature = bug_signature
    if len(violations) > 1:
      while self.bug_signature == "":
        msg.interactive("\n------------------------------------------\n")
        msg.interactive("Multiple violations detected! Choose one for MCS Finding:")
        for i, violation in enumerate(violations):
          msg.interactive("  [%d] %s" % (i+1, violation))
        violation_index = msg.raw_input("> ")
        if re.match("^\d+$", violation_index) is None or\
           int(violation_index) < 1 or\
           int(violation_index) > len(violations):
          msg.fail("Must provide an integer between 1 and %d!" % len(violations))
          continue
        self.bug_signature = violations[int(violation_index)-1]
    if self.bug_signature == "":
      self.bug_signature = violations[0]
    msg.success("\nBug signature to match is %s. Proceeding with MCS finding!\n" % self.bug_signature)

    self.transform_dag = transform_dag
    # A second log with just our MCS progress log messages
    self._extra_log = extra_log
    self.kwargs = kwargs
    unknown_kwargs = [ k for k in kwargs.keys() if k not in Replayer.kwargs ]
    if unknown_kwargs != []:
      raise ValueError("Unknown kwargs %s" % str(unknown_kwargs))
    if no_violation_verification_runs is not None:
      raise ValueError('''no_violation_verification_runs parameter is deprecated. '''
                       '''Use max_replays_per_subsequence.''')
    self.max_replays_per_subsequence = max_replays_per_subsequence
    self._runtime_stats = RuntimeStats(self.subsequence_id, runtime_stats_path=runtime_stats_path)
    # Whether to try alternate trace splitting techiques besides splitting by time.
    self.optimized_filtering = optimized_filtering
    self.forker = forker
    self.replay_final_trace = replay_final_trace
    self.strict_assertion_checking = strict_assertion_checking
Exemple #15
0
  def __init__(self, simulation_cfg, superlog_path_or_dag, create_event_scheduler=None,
               print_buffers=True, wait_on_deterministic_values=False, default_dp_permit=False,
               fail_to_interactive=False, fail_to_interactive_on_persistent_violations=False,
               end_in_interactive=False, input_logger=None,
               allow_unexpected_messages=False,
               expected_message_round_window=3,
               pass_through_whitelisted_messages=False,
               delay_flow_mods=False, invariant_check_name="",
               bug_signature="", end_wait_seconds=0.5,
               transform_dag=None, pass_through_sends=False,
               **kwargs):
    '''
     - If invariant_check_name is not None, check it at the end for the
       execution
     - If bug_signature is not None, check whether this particular signature
       appears in the output of the invariant check at the end of the
       execution
    '''
    ControlFlow.__init__(self, simulation_cfg)
    # Label uniquely identifying this replay, set in init_results()
    self.replay_id = "N/A"
    self.logical_time = 0
    if wait_on_deterministic_values:
      self.sync_callback = ReplaySyncCallback()
    else:
      self.sync_callback = ReplaySyncCallback(self.get_interpolated_time)

    if type(superlog_path_or_dag) == str:
      superlog_path = superlog_path_or_dag
      # The dag is codefied as a list, where each element has
      # a list of its dependents
      self.dag = EventDag(log_parser.parse_path(superlog_path))
    else:
      self.dag = superlog_path_or_dag

    if len(self.dag.events) == 0:
      raise ValueError("No events to replay!")

    self.default_dp_permit = default_dp_permit
    # Set DataplanePermit and DataplaneDrop to passive if permit is set
    # to default
    for event in [ e for e in self.dag.events if type(e) in dp_events ]:
      event.passive = default_dp_permit

    self.dp_checker = None
    no_dp_drops = [ e for e in self.dag.events if type(e) == DataplaneDrop ] == []
    if not default_dp_permit and no_dp_drops:
      print >> sys.stderr, ('''No DataplaneDrops to replay. We suggest you '''
                            '''set Replayer's default_dp_permit=True ''')
    if default_dp_permit:
      if no_dp_drops:
        self.dp_checker = AlwaysAllowDataplane(self.dag)
      else:
        self.dp_checker = DataplaneChecker(self.dag)

    self.print_buffers_flag = print_buffers

    # compute interpolate to time to be just before first event
    self.compute_interpolated_time(self.dag.events[0])
    # String repesentations of unexpected state changes we've passed through, for
    # statistics purposes.
    self.unexpected_state_changes = []
    self.early_state_changes = []
    self.event_scheduler_stats = None
    self.end_in_interactive = end_in_interactive
    self.fail_to_interactive = fail_to_interactive
    self.fail_to_interactive_on_persistent_violations =\
      fail_to_interactive_on_persistent_violations
    self._input_logger = input_logger
    self.allow_unexpected_messages = allow_unexpected_messages
    self.expected_message_round_window = expected_message_round_window
    self.pass_through_whitelisted_messages = pass_through_whitelisted_messages
    self.pass_through_sends = pass_through_sends
    # How many logical rounds to peek ahead when deciding if a message is
    # expected or not.
    # String repesentations of unexpected messages we've passed through, for
    # statistics purposes.
    self.passed_unexpected_messages = []
    self.delay_flow_mods = delay_flow_mods
    self.end_wait_seconds = end_wait_seconds
    self.transform_dag = transform_dag
    self.bug_signature = bug_signature
    self.invariant_check_name = invariant_check_name
    self.invariant_check = None
    if self.invariant_check_name:
      if self.invariant_check_name not in name_to_invariant_check:
        raise ValueError('''Unknown invariant check %s.\n'''
                         '''Invariant check name must be defined in config.invariant_checks''',
                         self.invariant_check_name)
      self.invariant_check = name_to_invariant_check[self.invariant_check_name]

    if self.pass_through_whitelisted_messages:
      for event in self.dag.events:
        if hasattr(event, "ignore_whitelisted_packets"):
          event.ignore_whitelisted_packets = True

    if create_event_scheduler:
      self.create_event_scheduler = create_event_scheduler
    else:
      self.create_event_scheduler = \
        lambda simulation: EventScheduler(simulation,
            **{ k: v for k,v in kwargs.items()
                if k in EventScheduler.kwargs })

    unknown_kwargs = [ k for k in kwargs.keys() if k not in EventScheduler.kwargs ]
    if unknown_kwargs != []:
      raise ValueError("Unknown kwargs %s" % str(unknown_kwargs))
Exemple #16
0
  def __init__(self, simulation_cfg, superlog_path_or_dag, create_event_scheduler=None,
               print_buffers=True, wait_on_deterministic_values=False, default_dp_permit=False,
               fail_to_interactive=False, fail_to_interactive_on_persistent_violations=False,
               end_in_interactive=False, input_logger=None,
               allow_unexpected_messages=False,
               pass_through_whitelisted_messages=True,
               delay_flow_mods=False,
               **kwargs):
    ControlFlow.__init__(self, simulation_cfg)
    if wait_on_deterministic_values:
      self.sync_callback = ReplaySyncCallback()
    else:
      self.sync_callback = ReplaySyncCallback(self.get_interpolated_time)

    if type(superlog_path_or_dag) == str:
      superlog_path = superlog_path_or_dag
      # The dag is codefied as a list, where each element has
      # a list of its dependents
      self.dag = EventDag(log_parser.parse_path(superlog_path))
    else:
      self.dag = superlog_path_or_dag

    if len(self.dag.events) == 0:
      raise ValueError("No events to replay!")

    self.default_dp_permit = default_dp_permit
    # Set DataplanePermit and DataplaneDrop to passive if permit is set
    # to default
    for event in [ e for e in self.dag.events if type(e) in dp_events ]:
      event.passive = default_dp_permit

    self.dp_checker = None
    if default_dp_permit:
      self.dp_checker = DataplaneChecker(self.dag)

    self.print_buffers_flag = print_buffers

    # compute interpolate to time to be just before first event
    self.compute_interpolated_time(self.dag.events[0])
    # String repesentations of unexpected state changes we've passed through, for
    # statistics purposes.
    self.unexpected_state_changes = []
    self.early_state_changes = []
    self.event_scheduler_stats = None
    self.end_in_interactive = end_in_interactive
    self.fail_to_interactive = fail_to_interactive
    self.fail_to_interactive_on_persistent_violations =\
      fail_to_interactive_on_persistent_violations
    self._input_logger = input_logger
    self.allow_unexpected_messages = allow_unexpected_messages
    self.pass_through_whitelisted_messages = pass_through_whitelisted_messages
    # How many logical rounds to peek ahead when deciding if a message is
    # expected or not.
    self.expected_message_round_window = 3
    # String repesentations of unexpected messages we've passed through, for
    # statistics purposes.
    self.passed_unexpected_messages = []
    self.delay_flow_mods = delay_flow_mods

    if self.pass_through_whitelisted_messages:
      for event in self.dag.events:
        if hasattr(event, "ignore_whitelisted_packets"):
          event.ignore_whitelisted_packets = True

    if create_event_scheduler:
      self.create_event_scheduler = create_event_scheduler
    else:
      self.create_event_scheduler = \
        lambda simulation: EventScheduler(simulation,
            **{ k: v for k,v in kwargs.items()
                if k in EventScheduler.kwargs })