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))
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())
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 ]
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
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 })
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))
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
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))
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
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))