Exemplo n.º 1
0
    def generate_test_cases_for_parser_paths(self, parser_paths):
        Statistics().init()
        self.total_switch_time = 0.0
        self.parser_path_edge_count = defaultdict(int)

        if Config().get_round_robin_parser_paths():
            results = self.generate_test_cases_round_robin(parser_paths)
        else:
            results = self.generate_test_cases_linearly(parser_paths)

        if self.table_solver is not None:
            self.table_solver.flush()

        logging.info("Final statistics on use of control path edges:")
        Statistics().log_control_path_stats(
            Statistics().stats_per_control_path_edge,
            Statistics().num_control_path_edges)
        self.test_case_writer.cleanup()

        Statistics().dump()
        Statistics().cleanup()

        for result, count in Statistics().stats.items():
            print('{}: {}'.format(result, count))

        if Config().get_dump_test_case():
            str_items = []
            for (parser_path, control_path), v in results.items():
                str_items.append('{}: {}'.format(
                    path_tuple(parser_path, control_path), v))
            print('{{ {} }}'.format(', '.join(str_items)))

        return results
Exemplo n.º 2
0
    def check_checksum_ipv4_with_options(self):
        Config().load_test_defaults()
        # This test case exercises variable-length extract, lookahead,
        # and verify statements in the parser.
        results = process_json_file('examples/checksum-ipv4-with-options.json')
        expected_results = {
            ('start', u'parse_ipv4', u'parse_tcp', 'sink', (u'node_2', (True, (u'p4_programs/checksum-ipv4-with-options.p4', 125, u'hdr.ipv4.isValid() && hdr.tcp.isValid()'))), (u'node_3', (True, (u'p4_programs/checksum-ipv4-with-options.p4', 130, u'hdr.ipv4.ihl == 14')))):
            TestPathResult.SUCCESS,
            ('start', u'parse_ipv4', u'parse_tcp', 'sink', (u'node_2', (True, (u'p4_programs/checksum-ipv4-with-options.p4', 125, u'hdr.ipv4.isValid() && hdr.tcp.isValid()'))), (u'node_3', (False, (u'p4_programs/checksum-ipv4-with-options.p4', 130, u'hdr.ipv4.ihl == 14'))), (u'guh', u'foo')):
            TestPathResult.SUCCESS,
            ('start', u'parse_ipv4', u'parse_tcp', 'sink', (u'node_2', (False, (u'p4_programs/checksum-ipv4-with-options.p4', 125, u'hdr.ipv4.isValid() && hdr.tcp.isValid()')))):
            TestPathResult.NO_PACKET_FOUND,
            ('start', u'parse_ipv4', 'sink', (u'node_2', (True, (u'p4_programs/checksum-ipv4-with-options.p4', 125, u'hdr.ipv4.isValid() && hdr.tcp.isValid()')))):
            TestPathResult.NO_PACKET_FOUND,
            ('start', u'parse_ipv4', 'sink', (u'node_2', (False, (u'p4_programs/checksum-ipv4-with-options.p4', 125, u'hdr.ipv4.isValid() && hdr.tcp.isValid()')))):
            TestPathResult.SUCCESS,

            # TBD Andy: What is this path doing in here?  It doesn't
            # look like a complete path to me for this program.
            ('start', u'parse_ipv4', 'sink'):
            TestPathResult.NO_PACKET_FOUND,
            ('start', 'sink', (u'node_2', (True, (u'p4_programs/checksum-ipv4-with-options.p4', 125, u'hdr.ipv4.isValid() && hdr.tcp.isValid()')))):
            TestPathResult.NO_PACKET_FOUND,
            ('start', 'sink', (u'node_2', (False, (u'p4_programs/checksum-ipv4-with-options.p4', 125, u'hdr.ipv4.isValid() && hdr.tcp.isValid()')))):
            TestPathResult.SUCCESS
        }
        assert results == expected_results
Exemplo n.º 3
0
    def __init__(self, json_file, pipeline, test_case_writer):
        # Only need to solve again on flush if randomizing.
        solve_again = Config().get_randomize()
        super(TableConsolidatedSolver,
              self).__init__(json_file, pipeline, test_case_writer,
                             solve_again)

        self.pipeline = pipeline
        for table in self.pipeline.tables.values():
            assert table.has_const_default_entry(), \
                "Tables with non-const defaults are not currently supported"

        # TODO: Consider implementing push/pop model for table_sym_vals and
        #  table_vars.  Harder than in base class as they're not simple lists.
        # List of consolidated symbolic keys and symbolic action params for the
        # table to use across all paths.
        # Currently only allowing a single key per action.
        self.table_action_sym_vals = {
        }  # {table_name: {action_name: (sym_key, sym_params)}}
        # Filled with any pending entries during add path, empty otherwise
        self.pending_table_action_sym_vals = {}

        # Filled with [(cmd, cmd_data), ...] during flush, None otherwise.
        self.table_setup_cmds = None

        # Object for managing table-data variables.
        self.table_vars = Variables()
Exemplo n.º 4
0
 def check_demo1b(self):
     Config().load_test_defaults()
     results = process_json_file('examples/demo1b.json')
     expected_results = {
         ('start', 'sink', (u'node_2', (True, (u'p4_programs/demo1b.p4', 141, u'hdr.ipv4.isValid()')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', u'parse_ipv4', 'sink', (u'node_2', (False, (u'p4_programs/demo1b.p4', 141, u'hdr.ipv4.isValid()')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', u'parse_ipv4', 'sink', (u'node_2', (True, (u'p4_programs/demo1b.p4', 141, u'hdr.ipv4.isValid()'))), (u'ipv4_acl', u'do_acl_permit'), (u'node_4', (True, (u'p4_programs/demo1b.p4', 143, u'acl_drop')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', u'parse_ipv4', 'sink', (u'node_2', (True, (u'p4_programs/demo1b.p4', 141, u'hdr.ipv4.isValid()'))), (u'ipv4_acl', u'do_acl_drop'), (u'node_4', (False, (u'p4_programs/demo1b.p4', 143, u'acl_drop')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', u'parse_ipv4', 'sink', (u'node_2', (True, (u'p4_programs/demo1b.p4', 141, u'hdr.ipv4.isValid()'))), (u'ipv4_acl', u'do_acl_permit'), (u'node_4', (False, (u'p4_programs/demo1b.p4', 143, u'acl_drop'))), (u'tbl_act_0', u'act_0'), (u'ipv4_da_lpm', u'my_drop'), (u'node_8', (True, (u'p4_programs/demo1b.p4', 149, u'meta.fwd_metadata.l2ptr != L2PTR_UNSET')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', 'sink', (u'node_2', (False, (u'p4_programs/demo1b.p4', 141, u'hdr.ipv4.isValid()')))):
         TestPathResult.SUCCESS,
         ('start', u'parse_ipv4', 'sink', (u'node_2', (True, (u'p4_programs/demo1b.p4', 141, u'hdr.ipv4.isValid()'))), (u'ipv4_acl', u'do_acl_drop'), (u'node_4', (True, (u'p4_programs/demo1b.p4', 143, u'acl_drop'))), (u'tbl_act', u'act')):
         TestPathResult.SUCCESS,
         ('start', u'parse_ipv4', 'sink', (u'node_2', (True, (u'p4_programs/demo1b.p4', 141, u'hdr.ipv4.isValid()'))), (u'ipv4_acl', u'do_acl_permit'), (u'node_4', (False, (u'p4_programs/demo1b.p4', 143, u'acl_drop'))), (u'tbl_act_0', u'act_0'), (u'ipv4_da_lpm', u'my_drop'), (u'node_8', (False, (u'p4_programs/demo1b.p4', 149, u'meta.fwd_metadata.l2ptr != L2PTR_UNSET')))):
         TestPathResult.SUCCESS,
         ('start', u'parse_ipv4', 'sink', (u'node_2', (True, (u'p4_programs/demo1b.p4', 141, u'hdr.ipv4.isValid()'))), (u'ipv4_acl', u'do_acl_permit'), (u'node_4', (False, (u'p4_programs/demo1b.p4', 143, u'acl_drop'))), (u'tbl_act_0', u'act_0'), (u'ipv4_da_lpm', u'set_l2ptr'), (u'node_8', (False, (u'p4_programs/demo1b.p4', 149, u'meta.fwd_metadata.l2ptr != L2PTR_UNSET')))):
         TestPathResult.SUCCESS,
         ('start', u'parse_ipv4', 'sink', (u'node_2', (True, (u'p4_programs/demo1b.p4', 141, u'hdr.ipv4.isValid()'))), (u'ipv4_acl', u'do_acl_permit'), (u'node_4', (False, (u'p4_programs/demo1b.p4', 143, u'acl_drop'))), (u'tbl_act_0', u'act_0'), (u'ipv4_da_lpm', u'set_l2ptr'), (u'node_8', (True, (u'p4_programs/demo1b.p4', 149, u'meta.fwd_metadata.l2ptr != L2PTR_UNSET'))), (u'mac_da', u'set_bd_dmac_intf')):
         TestPathResult.SUCCESS,
         ('start', u'parse_ipv4', 'sink', (u'node_2', (True, (u'p4_programs/demo1b.p4', 141, u'hdr.ipv4.isValid()'))), (u'ipv4_acl', u'do_acl_permit'), (u'node_4', (False, (u'p4_programs/demo1b.p4', 143, u'acl_drop'))), (u'tbl_act_0', u'act_0'), (u'ipv4_da_lpm', u'set_l2ptr'), (u'node_8', (True, (u'p4_programs/demo1b.p4', 149, u'meta.fwd_metadata.l2ptr != L2PTR_UNSET'))), (u'mac_da', u'my_drop')):
         TestPathResult.SUCCESS
     }
     assert results == expected_results
Exemplo n.º 5
0
    def preprocess_edges(self, path, edges):
        if Config().get_random_tlubf():
            shuffle(edges)
            return edges

        custom_order = sorted(
            edges, key=lambda t: Statistics().stats_per_control_path_edge[t])
        return reversed(custom_order)

        visited_es = []
        unvisited_es = []

        path_has_new_edges = False
        for e in path:
            if self.labels[e] == EdgeLabels.UNVISITED:
                path_has_new_edges = True
                break

        for e in edges:
            label = self.labels[e]
            if label == EdgeLabels.UNVISITED:
                unvisited_es.append(e)
            elif label == EdgeLabels.VISITED:
                visited_es.append(e)
            else:
                assert label == EdgeLabels.DONE
                if path_has_new_edges:
                    visited_es.append(e)

        # shuffle(visited_es)
        #shuffle(unvisited_es)
        return list(reversed(visited_es)) + list(reversed(unvisited_es))
Exemplo n.º 6
0
def generate_test_cases(input_file):
    top = P4_Top()
    top.load_json_file(input_file)

    top.build_graph()
    top.load_extern_backends()

    num_control_paths, num_control_path_nodes, num_control_path_edges = \
        top.in_graph.count_all_paths(top.in_pipeline.init_table_name)
    num_parser_path_edges = top.parser_graph.num_edges()
    Statistics(
    ).num_control_path_edges = num_parser_path_edges + num_control_path_edges

    graph_visitor = ParserGraphVisitor(top.hlir)
    parser_paths = [
        path for path in top.parser_graph.visit_all_paths(
            top.hlir.parsers['parser'].init_state, 'sink', graph_visitor)
    ]

    max_path_len = max([len(p) for p in parser_paths])
    logging.info("Found %d parser paths, longest with length %d"
                 "" % (len(parser_paths), max_path_len))
    if Config().get_show_parser_paths():
        print_parser_paths(parser_paths)

    logging.info(
        "Counted %d paths, %d nodes, %d edges"
        " in parser + ingress control flow graph"
        "" % (len(parser_paths) * num_control_paths, num_control_path_nodes,
              num_parser_path_edges + num_control_path_edges))

    generator = TestCaseGenerator(input_file, top)
    return generator.generate_test_cases_for_parser_paths(parser_paths)
Exemplo n.º 7
0
    def generate_test_cases_linearly(self, parser_paths):
        path_solver = PathSolver(self.top, self.top.in_pipeline)
        results = OrderedDict()

        for i_path, parser_path in enumerate(parser_paths):
            self.count_parser_path_edges(parser_path)
            logging.info("Analyzing parser_path %d of %d: %s"
                         "" % (i_path, len(parser_paths), parser_path))

            for path_model in self.iterate_paths_for_parser_path(
                    parser_path, results=results, path_solver=path_solver):
                for i_solution, path_solution in enumerate(
                        path_model.solutions()):
                    self.process_path_solution(path_solution)
                    logging.info("Processed %d solutions for path" %
                                 (i_solution + 1, ))

                    # If we have produced enough test cases overall, enough for this
                    # path, or have exhausted possible packets for this path, move on.
                    if enough_test_cases() or \
                            (i_solution + 1) == Config().get_max_test_cases_per_path():
                        break

                if enough_test_cases():
                    break

            if enough_test_cases():
                break

        return results
Exemplo n.º 8
0
    def generate_test_case_for_path(self, path_solution):
        path = path_solution.path
        context = path_solution.context
        sym_packet = path_solution.sym_packet
        model = path_solution.model

        start_time = time.time()
        build_result, test_case, payloads = \
            self.test_case_builder.build_for_path(
                context, model, sym_packet, path
            )
        assert build_result == path_solution.result
        test_case[
            "time_sec_generate_ingress_constraints"] = path_solution.time_sec_generate_ingress_constraints
        test_case["time_sec_solve"] = path_solution.time_sec_solve

        if Config().get_run_simple_switch():
            test_result = self.test_case_builder.run_simple_switch(
                path.expected_path, test_case, payloads, path.is_complete,
                self.top.in_source_info_to_node_name)
            assert test_result == path_solution.result

        self.total_switch_time += time.time() - start_time

        return (test_case, payloads)
Exemplo n.º 9
0
 def check_add_remove_header(self):
     Config().load_test_defaults()
     results = process_json_file('examples/add-remove-header.json')
     expected_results = {
         ('start', u'parse_ipv4', 'sink', (u'node_2', (True, (u'p4_programs/add-remove-header.p4', 144, u'hdr.ipv4.isValid()'))), (u'ipv4_da_lpm', u'set_l2ptr'), (u'node_4', (True, (u'p4_programs/add-remove-header.p4', 146, u'!hdr.outer_ipv4.isValid()'))), (u'mac_da', u'set_bd_dmac_intf')):
         TestPathResult.SUCCESS,
         ('start', u'parse_ipv4', 'sink', (u'node_2', (True, (u'p4_programs/add-remove-header.p4', 144, u'hdr.ipv4.isValid()'))), (u'ipv4_da_lpm', u'set_l2ptr'), (u'node_4', (True, (u'p4_programs/add-remove-header.p4', 146, u'!hdr.outer_ipv4.isValid()'))), (u'mac_da', u'my_drop')):
         TestPathResult.SUCCESS,
         ('start', u'parse_ipv4', 'sink', (u'node_2', (True, (u'p4_programs/add-remove-header.p4', 144, u'hdr.ipv4.isValid()'))), (u'ipv4_da_lpm', u'set_l2ptr'), (u'node_4', (False, (u'p4_programs/add-remove-header.p4', 146, u'!hdr.outer_ipv4.isValid()')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', u'parse_ipv4', 'sink', (u'node_2', (True, (u'p4_programs/add-remove-header.p4', 144, u'hdr.ipv4.isValid()'))), (u'ipv4_da_lpm', u'my_drop'), (u'node_4', (True, (u'p4_programs/add-remove-header.p4', 146, u'!hdr.outer_ipv4.isValid()'))), (u'mac_da', u'set_bd_dmac_intf')):
         TestPathResult.UNINITIALIZED_READ,
         ('start', u'parse_ipv4', 'sink', (u'node_2', (True, (u'p4_programs/add-remove-header.p4', 144, u'hdr.ipv4.isValid()'))), (u'ipv4_da_lpm', u'my_drop'), (u'node_4', (True, (u'p4_programs/add-remove-header.p4', 146, u'!hdr.outer_ipv4.isValid()'))), (u'mac_da', u'my_drop')):
         TestPathResult.UNINITIALIZED_READ,
         ('start', u'parse_ipv4', 'sink', (u'node_2', (True, (u'p4_programs/add-remove-header.p4', 144, u'hdr.ipv4.isValid()'))), (u'ipv4_da_lpm', u'my_drop'), (u'node_4', (False, (u'p4_programs/add-remove-header.p4', 146, u'!hdr.outer_ipv4.isValid()')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', u'parse_ipv4', 'sink', (u'node_2', (True, (u'p4_programs/add-remove-header.p4', 144, u'hdr.ipv4.isValid()'))), (u'ipv4_da_lpm', u'add_outer_ipv4'), (u'node_4', (True, (u'p4_programs/add-remove-header.p4', 146, u'!hdr.outer_ipv4.isValid()')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', u'parse_ipv4', 'sink', (u'node_2', (True, (u'p4_programs/add-remove-header.p4', 144, u'hdr.ipv4.isValid()'))), (u'ipv4_da_lpm', u'add_outer_ipv4'), (u'node_4', (False, (u'p4_programs/add-remove-header.p4', 146, u'!hdr.outer_ipv4.isValid()')))):
         TestPathResult.SUCCESS,
         ('start', u'parse_ipv4', 'sink', (u'node_2', (False, (u'p4_programs/add-remove-header.p4', 144, u'hdr.ipv4.isValid()')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', 'sink', (u'node_2', (True, (u'p4_programs/add-remove-header.p4', 144, u'hdr.ipv4.isValid()')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', 'sink', (u'node_2', (False, (u'p4_programs/add-remove-header.p4', 144, u'hdr.ipv4.isValid()')))):
         TestPathResult.SUCCESS
     }
     assert results == expected_results
Exemplo n.º 10
0
    def iterate_paths_for_parser_path(self,
                                      parser_path,
                                      results,
                                      path_solver=None):
        if path_solver is None:
            path_solver = PathSolver(self.top, self.top.in_pipeline)

        if not path_solver.generate_parser_constraints(parser_path):
            logging.info("Could not find any packet to satisfy parser path: %s"
                         "" % (parser_path))
            # Skip unsatisfiable parser paths
            return

        start_node, control_graph = self.get_control_graph()
        if Config().get_edge_coverage():
            graph_visitor = EdgeCoverageGraphVisitor(path_solver, parser_path,
                                                     results, control_graph)
        else:
            graph_visitor = PathCoverageGraphVisitor(path_solver, parser_path,
                                                     results)

        for path_model in control_graph.visit_all_paths(
                start_node, None, graph_visitor):
            # Only paths that will generate something useful
            if record_test_case(path_model.result,
                                path_model.path.is_complete):
                yield path_model
Exemplo n.º 11
0
    def choose_edge(self, edges):
        if Config().get_random_tlubf():
            return random.choice(edges)

        edge_counts = [self.path_count[e] for e in edges]
        min_index, min_value = min(enumerate(edge_counts),
                                   key=operator.itemgetter(1))
        return edges[min_index]
Exemplo n.º 12
0
    def __init__(self, input_file, top):
        self.input_file = input_file
        self.top = top
        self.total_switch_time = 0.0
        self.parser_path_edge_count = defaultdict(int)

        self.test_case_builder = TestCaseBuilder(input_file, top.in_pipeline)
        # TBD: Make this filename specifiable via command line option
        self.test_case_writer = TestCaseWriter(Config().get_output_json_path(),
                                               Config().get_output_pcap_path())
        self.table_solver = None
        if Config().get_do_consolidate_tables():
            # TODO: Remove this once these two options are made compatible
            assert Config().get_max_test_cases_per_path() == 1
            self.table_solver = \
                TableConsolidatedSolver(self.input_file, self.top.in_pipeline,
                                        self.test_case_writer)
Exemplo n.º 13
0
 def load_instances(self, extern_instances):
     extern_definitions = Config().get_extern_definitions()
     for name, instance in extern_instances.items():
         assert name in extern_definitions, \
             "Extern definition not provided for '{}'".format(name)
         src_file = extern_definitions[name]
         args = self.parse_instance_attribute_values(instance)
         self.extern_backends[name] = self.load_extern_instance(
             src_file, args)
Exemplo n.º 14
0
    def solutions(self):
        extract_vl_variation = Config().get_extract_vl_variation()
        current_result = self.result
        solve_time = self.time_sec_initial_solve
        while current_result != TestPathResult.NO_PACKET_FOUND:
            assert current_result == self.result

            # Choose values for randomization variables.
            random_constraints = []
            fix_random = self.path.is_complete
            if fix_random:
                self.path_solver.push()
                random_constraints = self.path_solver.fix_random_constraints()

            try:
                path_solution = PathSolution(
                    self.path,
                    self.result,
                    self.path_solver.constraints + [random_constraints],
                    self.path_solver.current_context(),
                    self.path_solver.sym_packet,
                    self.path_solver.solver.model(),
                    time_sec_generate_ingress_constraints=self.
                    time_sec_generate_ingress_constraints,
                    time_sec_solve=solve_time,
                )
                yield path_solution
            finally:
                # Clear the constraints on the values of the randomization
                # variables.
                if fix_random:
                    self.path_solver.pop()

            if not self.path_solver.constrain_last_extract_vl_lengths(
                    extract_vl_variation):
                # Special case: unbounded numbers of test cases are only
                # safe when we're building up constraints on VL-extraction
                # lengths, or else we'll loop forever.
                if not Config().get_max_test_cases_per_path():
                    break

            time2 = time.time()
            current_result = self.path_solver.solve_path()
            solve_time = time.time()
Exemplo n.º 15
0
    def visit_result(self, result):
        # TODO: Fix this option.
        if ge_than_not_none(self.success_path_count,
                            Config().get_max_paths_per_parser_path()):
            return VisitResult.BACKTRACK

        if result != TestPathResult.SUCCESS:
            return VisitResult.BACKTRACK

        return VisitResult.CONTINUE
Exemplo n.º 16
0
 def check_demo1_rm_header(self):
     Config().load_test_defaults()
     results = process_json_file('examples/demo1_rm_header.json')
     expected_results = {
         ('start', 'parse_ipv4', 'sink', (u'tbl_act', u'act')):
         TestPathResult.INVALID_HEADER_WRITE,
         ('start', 'sink', (u'tbl_act', u'act')):
         TestPathResult.INVALID_HEADER_WRITE
     }
     assert results == expected_results
Exemplo n.º 17
0
    def get_var(self, var_name):
        if var_name not in self.var_to_smt_val:
            # The variable that we're reading has not been set by the program.
            field = self.fields[var_name]
            new_var = self.fresh_var(var_name, field.size)
            if field.hdr.metadata and Config().get_solve_for_metadata():
                # We're solving for metadata.  Set the field to an
                # unconstrained value.
                self.set_field_value(var_name[0], var_name[1], new_var)
                self.input_metadata[var_name] = new_var
            elif Config().get_allow_uninitialized_reads():
                # Read the uninitialized value as zero.
                return BitVecVal(0, field.size)
            else:
                # If the header field has not been initialized, return a
                # fresh variable for each read access
                self.uninitialized_reads.append((var_name, self.source_info))
                return new_var

        assert var_name in self.var_to_smt_val
        return self.var_to_smt_val[var_name]
Exemplo n.º 18
0
 def get_var(self, var_name):
     if var_name not in self.var_to_smt_var:
         if Config().get_allow_uninitialized_reads():
             return BitVecVal(0, self.fields[var_name].size)
         else:
             # If the header field has not been initialized, return a fresh
             # variable for each read access
             self.uninitialized_reads.append((var_name, self.source_info))
             return BitVec(
                 self.fresh_var(var_name), self.fields[var_name].size)
     else:
         return self.var_to_smt_var[var_name]
Exemplo n.º 19
0
    def set_field_value(self, header_name, header_field, sym_val):
        # XXX: clean up
        if header_field != '$valid$' and (header_name,
                                          '$valid$') in self.var_to_smt_val:
            valid = self.var_to_smt_val[(header_name, '$valid$')]
            if simplify(valid) == BitVecVal(0, 1):
                if Config().get_allow_invalid_header_writes():
                    return
                else:
                    self.invalid_header_writes.append(
                        ((header_name, header_field), self.source_info))

        self.set_field_var(header_name, header_field, sym_val)
Exemplo n.º 20
0
 def new(self, name, size):
     """Creates a new variable with the specified name and size, with a
     random displacement if required.
     """
     var = z3.BitVec(name, size)
     # If we're randomizing, XOR in a variable that will be set to a random
     # value before the expression is evaluated.
     if Config().get_randomize():
         disp_name = '$rand_disp$.{}'.format(name)
         rand_disp = z3.BitVec(disp_name, size)
         self.rand_disp_vars.append(rand_disp)
         var ^= rand_disp
     return var
Exemplo n.º 21
0
    def __init__(self, json_file, hlir, pipeline):
        if Config().get_run_simple_switch():
            self.json_file = json_file
        else:
            self.json_file = None

        self.solver = Solver()
        self.solver.push()
        self.hlir = hlir
        self.pipeline = pipeline
        self.context_history = [Context()]  # XXX: implement better mechanism
        self.context_history_lens = []
        self.total_solver_time = 0.0
        self.total_switch_time = 0.0
Exemplo n.º 22
0
 def check_parser_impossible_transitions2_with_epl(self):
     Config().load_test_defaults(no_packet_length_errs=False)
     # Similar to the previous test case, this test case has
     # several parser paths that are impossible to traverse, and
     # several that are possible.
     results = process_json_file(
         'examples/parser-impossible-transitions2.json')
     expected_results = {
         ('start', 'sink', (u'node_2', (False, (u'parser-impossible-transitions2.p4', 110, u'hdr.ethernet.isValid()')))):
         TestPathResult.SUCCESS,
         ('start', 'sink', (u'node_2', (True, (u'parser-impossible-transitions2.p4', 110, u'hdr.ethernet.isValid()')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', 'parse_h5', 'sink', (u'node_2', (False, (u'parser-impossible-transitions2.p4', 110, u'hdr.ethernet.isValid()')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', 'parse_h5', 'sink', (u'node_2', (True, (u'parser-impossible-transitions2.p4', 110, u'hdr.ethernet.isValid()'))), (u'tbl_parserimpossibletransitions2l111', u'parserimpossibletransitions2l111'), (u'node_4', (False, (u'parser-impossible-transitions2.p4', 112, u'hdr.h1.isValid()'))), (u'node_6', (False, (u'parser-impossible-transitions2.p4', 114, u'hdr.h5.isValid()'))), (u'node_8', (False, (u'parser-impossible-transitions2.p4', 116, u'hdr.h2.isValid() || hdr.h3.isValid() || hdr.h4.isValid()'))), (u'node_15', (False, (u'parser-impossible-transitions2.p4', 126, u'hdr.ethernet.dstAddr == 0xffffffff')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', 'parse_h5', 'sink', (u'node_2', (True, (u'parser-impossible-transitions2.p4', 110, u'hdr.ethernet.isValid()'))), (u'tbl_parserimpossibletransitions2l111', u'parserimpossibletransitions2l111'), (u'node_4', (False, (u'parser-impossible-transitions2.p4', 112, u'hdr.h1.isValid()'))), (u'node_6', (False, (u'parser-impossible-transitions2.p4', 114, u'hdr.h5.isValid()'))), (u'node_8', (False, (u'parser-impossible-transitions2.p4', 116, u'hdr.h2.isValid() || hdr.h3.isValid() || hdr.h4.isValid()'))), (u'node_15', (True, (u'parser-impossible-transitions2.p4', 126, u'hdr.ethernet.dstAddr == 0xffffffff'))), (u'tbl_parserimpossibletransitions2l130', u'parserimpossibletransitions2l130')):
         TestPathResult.SUCCESS,
         ('start', 'parse_h5', 'sink', (u'node_2', (True, (u'parser-impossible-transitions2.p4', 110, u'hdr.ethernet.isValid()'))), (u'tbl_parserimpossibletransitions2l111', u'parserimpossibletransitions2l111'), (u'node_4', (False, (u'parser-impossible-transitions2.p4', 112, u'hdr.h1.isValid()'))), (u'node_6', (False, (u'parser-impossible-transitions2.p4', 114, u'hdr.h5.isValid()'))), (u'node_8', (True, (u'parser-impossible-transitions2.p4', 116, u'hdr.h2.isValid() || hdr.h3.isValid() || hdr.h4.isValid()')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', 'parse_h5', 'sink', (u'node_2', (True, (u'parser-impossible-transitions2.p4', 110, u'hdr.ethernet.isValid()'))), (u'tbl_parserimpossibletransitions2l111', u'parserimpossibletransitions2l111'), (u'node_4', (False, (u'parser-impossible-transitions2.p4', 112, u'hdr.h1.isValid()'))), (u'node_6', (True, (u'parser-impossible-transitions2.p4', 114, u'hdr.h5.isValid()')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', 'parse_h5', 'sink', (u'node_2', (True, (u'parser-impossible-transitions2.p4', 110, u'hdr.ethernet.isValid()'))), (u'tbl_parserimpossibletransitions2l111', u'parserimpossibletransitions2l111'), (u'node_4', (True, (u'parser-impossible-transitions2.p4', 112, u'hdr.h1.isValid()')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', 'parse_h5', 'sink', (u'node_2', (True, (u'parser-impossible-transitions2.p4', 110, u'hdr.ethernet.isValid()'))), (u'tbl_parserimpossibletransitions2l111', u'parserimpossibletransitions2l111'), (u'node_4', (False, (u'parser-impossible-transitions2.p4', 112, u'hdr.h1.isValid()'))), (u'node_6', (False, (u'parser-impossible-transitions2.p4', 114, u'hdr.h5.isValid()')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', 'parse_h5', 'sink', (u'node_2', (True, (u'parser-impossible-transitions2.p4', 110, u'hdr.ethernet.isValid()'))), (u'tbl_parserimpossibletransitions2l111', u'parserimpossibletransitions2l111'), (u'node_4', (False, (u'parser-impossible-transitions2.p4', 112, u'hdr.h1.isValid()'))), (u'node_6', (True, (u'parser-impossible-transitions2.p4', 114, u'hdr.h5.isValid()'))), (u'tbl_parserimpossibletransitions2l115', u'parserimpossibletransitions2l115'), (u'node_15', (False, (u'parser-impossible-transitions2.p4', 126, u'hdr.ethernet.dstAddr == 0xffffffff'))), (u'tbl_parserimpossibletransitions2l132', u'parserimpossibletransitions2l132')):
         TestPathResult.SUCCESS,
         ('start', 'parse_h5', 'sink', (u'node_2', (True, (u'parser-impossible-transitions2.p4', 110, u'hdr.ethernet.isValid()'))), (u'tbl_parserimpossibletransitions2l111', u'parserimpossibletransitions2l111'), (u'node_4', (False, (u'parser-impossible-transitions2.p4', 112, u'hdr.h1.isValid()'))), (u'node_6', (True, (u'parser-impossible-transitions2.p4', 114, u'hdr.h5.isValid()'))), (u'tbl_parserimpossibletransitions2l115', u'parserimpossibletransitions2l115'), (u'node_15', (True, (u'parser-impossible-transitions2.p4', 126, u'hdr.ethernet.dstAddr == 0xffffffff')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', 'parse_h1', 'sink', (u'node_2', (False, (u'parser-impossible-transitions2.p4', 110, u'hdr.ethernet.isValid()')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', 'parse_h1', 'sink', (u'node_2', (True, (u'parser-impossible-transitions2.p4', 110, u'hdr.ethernet.isValid()'))), (u'tbl_parserimpossibletransitions2l111', u'parserimpossibletransitions2l111'), (u'node_4', (False, (u'parser-impossible-transitions2.p4', 112, u'hdr.h1.isValid()'))), (u'node_6', (False, (u'parser-impossible-transitions2.p4', 114, u'hdr.h5.isValid()'))), (u'node_8', (False, (u'parser-impossible-transitions2.p4', 116, u'hdr.h2.isValid() || hdr.h3.isValid() || hdr.h4.isValid()'))), (u'node_15', (False, (u'parser-impossible-transitions2.p4', 126, u'hdr.ethernet.dstAddr == 0xffffffff')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', 'parse_h1', 'sink', (u'node_2', (True, (u'parser-impossible-transitions2.p4', 110, u'hdr.ethernet.isValid()'))), (u'tbl_parserimpossibletransitions2l111', u'parserimpossibletransitions2l111'), (u'node_4', (False, (u'parser-impossible-transitions2.p4', 112, u'hdr.h1.isValid()'))), (u'node_6', (False, (u'parser-impossible-transitions2.p4', 114, u'hdr.h5.isValid()'))), (u'node_8', (False, (u'parser-impossible-transitions2.p4', 116, u'hdr.h2.isValid() || hdr.h3.isValid() || hdr.h4.isValid()'))), (u'node_15', (True, (u'parser-impossible-transitions2.p4', 126, u'hdr.ethernet.dstAddr == 0xffffffff'))), (u'tbl_parserimpossibletransitions2l130', u'parserimpossibletransitions2l130')):
         TestPathResult.SUCCESS,
         ('start', 'parse_h1', 'sink', (u'node_2', (True, (u'parser-impossible-transitions2.p4', 110, u'hdr.ethernet.isValid()'))), (u'tbl_parserimpossibletransitions2l111', u'parserimpossibletransitions2l111'), (u'node_4', (False, (u'parser-impossible-transitions2.p4', 112, u'hdr.h1.isValid()'))), (u'node_6', (False, (u'parser-impossible-transitions2.p4', 114, u'hdr.h5.isValid()'))), (u'node_8', (True, (u'parser-impossible-transitions2.p4', 116, u'hdr.h2.isValid() || hdr.h3.isValid() || hdr.h4.isValid()')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', 'parse_h1', 'sink', (u'node_2', (True, (u'parser-impossible-transitions2.p4', 110, u'hdr.ethernet.isValid()'))), (u'tbl_parserimpossibletransitions2l111', u'parserimpossibletransitions2l111'), (u'node_4', (False, (u'parser-impossible-transitions2.p4', 112, u'hdr.h1.isValid()'))), (u'node_6', (True, (u'parser-impossible-transitions2.p4', 114, u'hdr.h5.isValid()')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', 'parse_h1', 'sink', (u'node_2', (True, (u'parser-impossible-transitions2.p4', 110, u'hdr.ethernet.isValid()'))), (u'tbl_parserimpossibletransitions2l111', u'parserimpossibletransitions2l111'), (u'node_4', (True, (u'parser-impossible-transitions2.p4', 112, u'hdr.h1.isValid()')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', 'parse_h1', 'sink', (u'node_2', (True, (u'parser-impossible-transitions2.p4', 110, u'hdr.ethernet.isValid()'))), (u'tbl_parserimpossibletransitions2l111', u'parserimpossibletransitions2l111'), (u'node_4', (False, (u'parser-impossible-transitions2.p4', 112, u'hdr.h1.isValid()')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', 'parse_h1', 'sink', (u'node_2', (True, (u'parser-impossible-transitions2.p4', 110, u'hdr.ethernet.isValid()'))), (u'tbl_parserimpossibletransitions2l111', u'parserimpossibletransitions2l111'), (u'node_4', (True, (u'parser-impossible-transitions2.p4', 112, u'hdr.h1.isValid()'))), (u'tbl_parserimpossibletransitions2l113', u'parserimpossibletransitions2l113'), (u'node_15', (False, (u'parser-impossible-transitions2.p4', 126, u'hdr.ethernet.dstAddr == 0xffffffff'))), (u'tbl_parserimpossibletransitions2l132', u'parserimpossibletransitions2l132')):
         TestPathResult.SUCCESS,
         ('start', 'parse_h1', 'sink', (u'node_2', (True, (u'parser-impossible-transitions2.p4', 110, u'hdr.ethernet.isValid()'))), (u'tbl_parserimpossibletransitions2l111', u'parserimpossibletransitions2l111'), (u'node_4', (True, (u'parser-impossible-transitions2.p4', 112, u'hdr.h1.isValid()'))), (u'tbl_parserimpossibletransitions2l113', u'parserimpossibletransitions2l113'), (u'node_15', (True, (u'parser-impossible-transitions2.p4', 126, u'hdr.ethernet.dstAddr == 0xffffffff')))):
         TestPathResult.NO_PACKET_FOUND
     }
     assert results == expected_results
Exemplo n.º 23
0
    def set_field_value(self, header_name, header_field, sym_val):
        var_name = '{}.{}'.format(header_name, header_field)
        do_write = True
        # XXX: clean up
        if header_field != '$valid$' and ('{}.{}'.format(
                header_name, '$valid$') in self.sym_vars) and simplify(
                    self.get_header_field(header_name,
                                          '$valid$')) == BitVecVal(0, 1):
            if Config().get_allow_invalid_header_writes():
                do_write = False
            else:
                self.invalid_header_writes.append((var_name, self.source_info))

        if do_write:
            self.sym_vars[var_name] = sym_val
Exemplo n.º 24
0
    def preprocess_edges(self, path_prefix, onward_edges):
        # Count the number of extractions for each header stack in the path so
        # far.
        stack_counts = defaultdict(int)
        if len(path_prefix) > 0:
            self.count(stack_counts, path_prefix[0].src)
            for e in path_prefix:
                self.count(stack_counts, e.dst)

        edges = onward_edges

        if any(
                self.hlir.get_header_stack(stack).size < count
                for stack, count in stack_counts.items()):
            # If the path so far involves an extraction beyond the end of a
            # header stack, the only legal onward transitions are error
            # transitions.  If there are no such transitions, the returned list
            # will be empty, which will cause the caller to drop the current
            # path-prefix entirely.
            edges = [
                edge for edge in edges
                if isinstance(edge, ParserErrorTransition)
            ]
        elif Config().get_collapse_parser_paths():
            # Collapse any parallel transitions into a single edge with merged
            # constraints.  Note that although the nodes on either side of the
            # new edge are part of the graph, the edge itself is not.
            good_edges = [
                edge for edge in edges if isinstance(edge, ParserTransition)
            ]
            other_edges = [
                edge for edge in edges
                if not isinstance(edge, ParserTransition)
            ]

            good_edges_by_next_state = defaultdict(list)
            for edge in good_edges:
                good_edges_by_next_state[edge.next_state_name].append(edge)

            edges = other_edges
            for grouped_edges in good_edges_by_next_state.values():
                if len(grouped_edges) == 1:
                    edges.append(grouped_edges[0])
                else:
                    assert len(grouped_edges) > 1
                    edges.append(ParserCompositeTransition(grouped_edges))

        return edges
Exemplo n.º 25
0
    def init(self):
        self.num_control_path_edges = 0
        self.avg_full_path_len = Average('full_path_len')
        self.avg_unsat_path_len = Average('unsat_path_len')
        self.count_unsat_paths = Counter('unsat_paths')

        self.timing_file = None
        self.breakdown_file = None
        if Config().get_record_statistics():
            self.timing_file = open('timing.log', 'w')
            self.breakdown_file = open('breakdown.log', 'w')

        self.start_time = time.time()
        self.stats = defaultdict(int)
        self.stats_per_control_path_edge = defaultdict(int)
        self.last_time_printed_stats_per_control_path_edge = self.start_time
        self.record_count = 0
Exemplo n.º 26
0
 def check_demo1(self):
     Config().load_test_defaults()
     results = process_json_file(
         'examples/demo1-action-names-uniquified.p4_16.json')
     expected_results = {
         ('start', 'sink', (u'ipv4_da_lpm', u'set_l2ptr')):
         TestPathResult.UNINITIALIZED_READ,
         ('start', 'sink', (u'ipv4_da_lpm', u'my_drop1')):
         TestPathResult.UNINITIALIZED_READ,
         ('start', 'parse_ipv4', 'sink', (u'ipv4_da_lpm', u'set_l2ptr'), (u'mac_da', u'set_bd_dmac_intf')):
         TestPathResult.SUCCESS,
         ('start', 'parse_ipv4', 'sink', (u'ipv4_da_lpm', u'set_l2ptr'), (u'mac_da', u'my_drop2')):
         TestPathResult.SUCCESS,
         ('start', 'parse_ipv4', 'sink', (u'ipv4_da_lpm', u'my_drop1'), (u'mac_da', u'set_bd_dmac_intf')):
         TestPathResult.UNINITIALIZED_READ,
         ('start', 'parse_ipv4', 'sink', (u'ipv4_da_lpm', u'my_drop1'), (u'mac_da', u'my_drop2')):
         TestPathResult.UNINITIALIZED_READ
     }
     assert results == expected_results
Exemplo n.º 27
0
 def check_parser_impossible_transitions(self):
     Config().load_test_defaults()
     # This test case has at least one parser path that is
     # impossible to traverse, and several that are possible that,
     # when taken, make certain paths through ingress impossible.
     # Note that there are no test cases containing the state
     # parse_unreachable_state in the parser paths.
     results = process_json_file(
         'examples/parser-impossible-transitions.json')
     expected_results = {
         ('start', 'parse_good', 'sink', (u'node_2', (False, (u'parser-impossible-transitions.p4', 92, u'meta.fwd_metadata.parse_status == 0')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', 'parse_good', 'sink', (u'node_2', (True, (u'parser-impossible-transitions.p4', 92, u'meta.fwd_metadata.parse_status == 0'))), (u'node_3', (False, (u'parser-impossible-transitions.p4', 93, u'hdr.ethernet.etherType_lsb == 4')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', 'parse_good', 'sink', (u'node_2', (True, (u'parser-impossible-transitions.p4', 92, u'meta.fwd_metadata.parse_status == 0'))), (u'node_3', (True, (u'parser-impossible-transitions.p4', 93, u'hdr.ethernet.etherType_lsb == 4'))), (u'tbl_parserimpossibletransitions94', u'parserimpossibletransitions94')):
         TestPathResult.SUCCESS,
         ('start', 'parse_bad4', 'sink', (u'node_2', (False, (u'parser-impossible-transitions.p4', 92, u'meta.fwd_metadata.parse_status == 0'))), (u'node_6', (False, (u'parser-impossible-transitions.p4', 99, u'meta.fwd_metadata.parse_status <= 4')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', 'parse_bad4', 'sink', (u'node_2', (False, (u'parser-impossible-transitions.p4', 92, u'meta.fwd_metadata.parse_status == 0'))), (u'node_6', (True, (u'parser-impossible-transitions.p4', 99, u'meta.fwd_metadata.parse_status <= 4'))), (u'tbl_parserimpossibletransitions100', u'parserimpossibletransitions100')):
         TestPathResult.SUCCESS,
         ('start', 'parse_bad4', 'sink', (u'node_2', (True, (u'parser-impossible-transitions.p4', 92, u'meta.fwd_metadata.parse_status == 0')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', 'parse_bad3', 'sink', (u'node_2', (False, (u'parser-impossible-transitions.p4', 92, u'meta.fwd_metadata.parse_status == 0'))), (u'node_6', (False, (u'parser-impossible-transitions.p4', 99, u'meta.fwd_metadata.parse_status <= 4')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', 'parse_bad3', 'sink', (u'node_2', (False, (u'parser-impossible-transitions.p4', 92, u'meta.fwd_metadata.parse_status == 0'))), (u'node_6', (True, (u'parser-impossible-transitions.p4', 99, u'meta.fwd_metadata.parse_status <= 4'))), (u'tbl_parserimpossibletransitions100', u'parserimpossibletransitions100')):
         TestPathResult.SUCCESS,
         ('start', 'parse_bad3', 'sink', (u'node_2', (True, (u'parser-impossible-transitions.p4', 92, u'meta.fwd_metadata.parse_status == 0')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', 'parse_bad2', 'sink', (u'node_2', (False, (u'parser-impossible-transitions.p4', 92, u'meta.fwd_metadata.parse_status == 0'))), (u'node_6', (False, (u'parser-impossible-transitions.p4', 99, u'meta.fwd_metadata.parse_status <= 4')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', 'parse_bad2', 'sink', (u'node_2', (False, (u'parser-impossible-transitions.p4', 92, u'meta.fwd_metadata.parse_status == 0'))), (u'node_6', (True, (u'parser-impossible-transitions.p4', 99, u'meta.fwd_metadata.parse_status <= 4'))), (u'tbl_parserimpossibletransitions100', u'parserimpossibletransitions100')):
         TestPathResult.SUCCESS,
         ('start', 'parse_bad2', 'sink', (u'node_2', (True, (u'parser-impossible-transitions.p4', 92, u'meta.fwd_metadata.parse_status == 0')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', 'parse_bad1', 'sink', (u'node_2', (False, (u'parser-impossible-transitions.p4', 92, u'meta.fwd_metadata.parse_status == 0'))), (u'node_6', (False, (u'parser-impossible-transitions.p4', 99, u'meta.fwd_metadata.parse_status <= 4')))):
         TestPathResult.NO_PACKET_FOUND,
         ('start', 'parse_bad1', 'sink', (u'node_2', (False, (u'parser-impossible-transitions.p4', 92, u'meta.fwd_metadata.parse_status == 0'))), (u'node_6', (True, (u'parser-impossible-transitions.p4', 99, u'meta.fwd_metadata.parse_status <= 4'))), (u'tbl_parserimpossibletransitions100', u'parserimpossibletransitions100')):
         TestPathResult.SUCCESS,
         ('start', 'parse_bad1', 'sink', (u'node_2', (True, (u'parser-impossible-transitions.p4', 92, u'meta.fwd_metadata.parse_status == 0')))):
         TestPathResult.NO_PACKET_FOUND
     }
     assert results == expected_results
Exemplo n.º 28
0
    def _add_path(self, path_id, constraints, path_data):
        # note: constraints is a list of lists, each sub-list represents the
        # constraints added by a single transition.
        max_n_paths = Config().get_consolidate_tables()
        if len(self.paths_data) == max_n_paths:
            logging.info("Too many paths-per-solve")
            self.flush()

        self.push(path_id, path_data)
        if not self._try_add_path(path_id, constraints, path_data):
            logging.info("Failed to add path %d" % (path_id, ))
            self.pop()
            self.flush()
            self.reset()
            self.push(path_id, path_data)
            logging.info("Flushed existing paths, re-adding path %d" %
                         (path_id, ))
            assert self._try_add_path(path_id, constraints, path_data)
        else:
            logging.info("Successfully added path %d" % (path_id, ))
Exemplo n.º 29
0
    def solve_path(self, control_path, is_complete_control_path):
        expected_path = list(
            self.path_solver.translator.expected_path(self.parser_path,
                                                      control_path))

        path = Path(self.path_solver.path_id, expected_path, self.parser_path,
                    control_path, is_complete_control_path)

        logging.info("")
        logging.info("BEGIN %s" % str(path))

        if not Config().get_incremental():
            self.path_solver.solver.reset()

        time1 = time.time()
        self.path_solver.add_path_constraints(control_path)
        time2 = time.time()

        result = self.path_solver.try_quick_solve(control_path,
                                                  is_complete_control_path)
        if result == TestPathResult.SUCCESS:
            assert not (record_path_result(result, is_complete_control_path)
                        or record_test_case(result, is_complete_control_path))
            # Path trivially found to be satisfiable and not complete.
            # No test cases required.
            logging.info(
                "Path trivially found to be satisfiable and not complete.")
            logging.info("END   %s" % str(path))
            return result, None

        result = self.path_solver.solve_path()
        time3 = time.time()

        logging.info("END   %s: %s" % (str(path), result))
        path_model = PathModel(path,
                               result,
                               self.path_solver,
                               time_sec_generate_ingress_constraints=time2 -
                               time1,
                               time_sec_initial_solve=time3 - time2)
        return result, path_model
Exemplo n.º 30
0
 def check_demo9b(self):
     Config().load_test_defaults()
     results = process_json_file('examples/demo9b.json')
     expected_results = {
         ('start', 'parse_ethernet', 'sink', (u'node_2', (False, (u'p4_programs/demo9b.p4', 157, u'hdr.ipv6.version != 6')))):
         TestPathResult.UNINITIALIZED_READ,
         ('start', 'parse_ethernet', 'sink', (u'node_2', (True, (u'p4_programs/demo9b.p4', 157, u'hdr.ipv6.version != 6')))):
         TestPathResult.UNINITIALIZED_READ,
         ('start', 'parse_ethernet', 'parse_ipv4', 'sink', (u'node_2', (False, (u'p4_programs/demo9b.p4', 157, u'hdr.ipv6.version != 6')))):
         TestPathResult.UNINITIALIZED_READ,
         ('start', 'parse_ethernet', 'parse_ipv4', 'sink', (u'node_2', (True, (u'p4_programs/demo9b.p4', 157, u'hdr.ipv6.version != 6')))):
         TestPathResult.UNINITIALIZED_READ,
         ('start', 'parse_ethernet', 'parse_ipv4', 'parse_tcp', 'sink', (u'node_2', (False, (u'p4_programs/demo9b.p4', 157, u'hdr.ipv6.version != 6')))):
         TestPathResult.UNINITIALIZED_READ,
         ('start', 'parse_ethernet', 'parse_ipv4', 'parse_tcp', 'sink', (u'node_2', (True, (u'p4_programs/demo9b.p4', 157, u'hdr.ipv6.version != 6')))):
         TestPathResult.UNINITIALIZED_READ,
         ('start', 'parse_ethernet', 'parse_ipv4', 'parse_udp', 'sink', (u'node_2', (True, (u'p4_programs/demo9b.p4', 157, u'hdr.ipv6.version != 6')))):
         TestPathResult.UNINITIALIZED_READ,
         ('start', 'parse_ethernet', 'parse_ipv4', 'parse_udp', 'sink', (u'node_2', (False, (u'p4_programs/demo9b.p4', 157, u'hdr.ipv6.version != 6')))):
         TestPathResult.UNINITIALIZED_READ,
         ('start', 'parse_ethernet', 'parse_ipv6', 'sink', (u'node_2', (True, (u'p4_programs/demo9b.p4', 157, u'hdr.ipv6.version != 6')))):
         TestPathResult.SUCCESS,
         ('start', 'parse_ethernet', 'parse_ipv6', 'parse_tcp', 'sink', (u'node_2', (True, (u'p4_programs/demo9b.p4', 157, u'hdr.ipv6.version != 6')))):
         TestPathResult.SUCCESS,
         ('start', 'parse_ethernet', 'parse_ipv6', 'parse_udp', 'sink', (u'node_2', (True, (u'p4_programs/demo9b.p4', 157, u'hdr.ipv6.version != 6')))):
         TestPathResult.SUCCESS,
         ('start', 'parse_ethernet', 'parse_ipv6', 'sink', (u'node_2', (False, (u'p4_programs/demo9b.p4', 157, u'hdr.ipv6.version != 6'))), (u'node_3', (False, (u'p4_programs/demo9b.p4', 160, u'hdr.ethernet.srcAddr == 123456'))), (u'tbl_act_0', u'act_0')):
         TestPathResult.SUCCESS,
         ('start', 'parse_ethernet', 'parse_ipv6', 'sink', (u'node_2', (False, (u'p4_programs/demo9b.p4', 157, u'hdr.ipv6.version != 6'))), (u'node_3', (True, (u'p4_programs/demo9b.p4', 160, u'hdr.ethernet.srcAddr == 123456'))), (u'tbl_act', u'act')):
         TestPathResult.SUCCESS,
         ('start', 'parse_ethernet', 'parse_ipv6', 'parse_tcp', 'sink', (u'node_2', (False, (u'p4_programs/demo9b.p4', 157, u'hdr.ipv6.version != 6'))), (u'node_3', (False, (u'p4_programs/demo9b.p4', 160, u'hdr.ethernet.srcAddr == 123456'))), (u'tbl_act_0', u'act_0')):
         TestPathResult.SUCCESS,
         ('start', 'parse_ethernet', 'parse_ipv6', 'parse_tcp', 'sink', (u'node_2', (False, (u'p4_programs/demo9b.p4', 157, u'hdr.ipv6.version != 6'))), (u'node_3', (True, (u'p4_programs/demo9b.p4', 160, u'hdr.ethernet.srcAddr == 123456'))), (u'tbl_act', u'act')):
         TestPathResult.SUCCESS,
         ('start', 'parse_ethernet', 'parse_ipv6', 'parse_udp', 'sink', (u'node_2', (False, (u'p4_programs/demo9b.p4', 157, u'hdr.ipv6.version != 6'))), (u'node_3', (False, (u'p4_programs/demo9b.p4', 160, u'hdr.ethernet.srcAddr == 123456'))), (u'tbl_act_0', u'act_0')):
         TestPathResult.SUCCESS,
         ('start', 'parse_ethernet', 'parse_ipv6', 'parse_udp', 'sink', (u'node_2', (False, (u'p4_programs/demo9b.p4', 157, u'hdr.ipv6.version != 6'))), (u'node_3', (True, (u'p4_programs/demo9b.p4', 160, u'hdr.ethernet.srcAddr == 123456'))), (u'tbl_act', u'act')):
         TestPathResult.SUCCESS
     }
     assert results == expected_results