Exemple #1
0
    def handle_select(self, p4_state):
        switches = []
        select_conds = []
        context = p4_state.current_context()
        forward_cond_copy = context.tmp_forward_cond
        match_list = p4_state.resolve_expr(self.match)
        for parser_cond, parser_node in reversed(self.child):
            case_expr = p4_state.resolve_expr(parser_cond)
            cond = build_select_cond(p4_state, case_expr, match_list)
            # state forks here
            var_store, contexts = p4_state.checkpoint()
            context.tmp_forward_cond = z3.And(forward_cond_copy, cond)
            parser_node.eval(p4_state)
            select_conds.append(cond)
            if not p4_state.has_exited:
                switches.append(
                    (context.tmp_forward_cond, p4_state.get_attrs()))
            p4_state.has_exited = False
            context.has_returned = False
            p4_state.restore(var_store, contexts)

        # this hits when the table is either missed, or no action matches
        cond = z3.Not(z3.Or(*select_conds))
        context.tmp_forward_cond = z3.And(forward_cond_copy, cond)
        self.default.eval(p4_state)
        p4_state.has_exited = False
        context.has_returned = False
        context.tmp_forward_cond = forward_cond_copy
        for cond, then_vars in switches:
            merge_attrs(p4_state, cond, then_vars)
Exemple #2
0
    def handle_select(self, ctx):
        switches = []
        select_conds = []
        forward_cond_copy = ctx.tmp_forward_cond
        match_list = ctx.resolve_expr(self.match)
        for parser_cond, parser_node in self.child:
            case_expr = ctx.resolve_expr(parser_cond)
            cond = build_select_cond(ctx, case_expr, match_list)
            # state forks here
            var_store = ctx.checkpoint()
            ctx.tmp_forward_cond = z3.And(forward_cond_copy, cond)
            parser_node.eval(ctx)
            select_conds.append(cond)
            if not (ctx.get_exited() or z3.is_false(cond)):
                switches.append((ctx.tmp_forward_cond, ctx.get_attrs()))
            ctx.set_exited(False)
            ctx.has_returned = False
            ctx.restore(var_store)

        # this hits when no select matches
        cond = z3.Not(z3.Or(*select_conds))
        ctx.tmp_forward_cond = z3.And(forward_cond_copy, cond)
        self.default.eval(ctx)
        ctx.set_exited(False)
        ctx.has_returned = False
        ctx.tmp_forward_cond = forward_cond_copy
        for cond, then_vars in reversed(switches):
            merge_attrs(ctx, cond, then_vars)
Exemple #3
0
    def eval(self, ctx):
        cond = z3.simplify(ctx.resolve_expr(self.cond))
        forward_cond_copy = ctx.tmp_forward_cond
        then_vars = None
        if not z3.is_false(cond):
            var_store = ctx.checkpoint()
            ctx.tmp_forward_cond = z3.And(forward_cond_copy, cond)
            try:
                self.then_block.eval(ctx)
            except ParserException:
                RejectState().eval(ctx)
            if not(ctx.has_returned or ctx.get_exited()):
                then_vars = ctx.get_attrs()
            ctx.set_exited(False)
            ctx.has_returned = False
            ctx.restore(var_store)

        if not z3.is_true(cond):
            var_store = ctx.checkpoint()
            ctx.tmp_forward_cond = z3.And(forward_cond_copy, z3.Not(cond))
            try:
                self.else_block.eval(ctx)
            except ParserException:
                RejectState().eval(ctx)
            if ctx.get_exited() or ctx.has_returned:
                ctx.restore(var_store)
            ctx.set_exited(False)
            ctx.has_returned = False

        ctx.tmp_forward_cond = forward_cond_copy

        if then_vars:
            merge_attrs(ctx, cond, then_vars)
Exemple #4
0
    def eval_table(self, p4_state):
        action_exprs = []
        action_matches = []
        context = p4_state.current_context()
        forward_cond_copy = context.tmp_forward_cond

        # only bother to evaluate if the table can actually hit
        if not self.locals["hit"] == z3.BoolVal(False):
            # note: the action lists are pass by reference here
            # first evaluate all the constant entries
            self.eval_const_entries(p4_state, action_exprs, action_matches)
            # then append dynamic table entries to the constant entries
            self.eval_table_entries(p4_state, action_exprs, action_matches)
        # finally start evaluating the default entry
        var_store, contexts = p4_state.checkpoint()
        # this hits when the table is either missed, or no action matches
        cond = z3.Or(self.locals["miss"], z3.Not(z3.Or(*action_matches)))
        context.tmp_forward_cond = z3.And(forward_cond_copy, cond)
        self.eval_default(p4_state)
        if p4_state.has_exited:
            p4_state.restore(var_store, contexts)
        p4_state.has_exited = False
        context.tmp_forward_cond = forward_cond_copy
        # generate a nested set of if expressions per available action
        for cond, then_vars in action_exprs:
            merge_attrs(p4_state, cond, then_vars)
Exemple #5
0
    def eval_table(self, ctx):
        action_exprs = []
        action_matches = []
        forward_cond_copy = ctx.tmp_forward_cond

        # only bother to evaluate if the table can actually hit
        if not z3.is_false(self.locals["hit"]):
            # note: the action lists are pass by reference here
            # first evaluate all the constant entries
            self.eval_const_entries(ctx, action_exprs, action_matches)
            # then append dynamic table entries to the constant entries
            # only do this if the table can actually be manipulated
            if not self.immutable:
                self.eval_table_entries(ctx, action_exprs, action_matches)
        # finally start evaluating the default entry
        var_store = ctx.checkpoint()
        # this hits when the table is either missed, or no action matches
        cond = z3.Or(self.locals["miss"], z3.Not(z3.Or(*action_matches)))
        ctx.tmp_forward_cond = z3.And(forward_cond_copy, cond)
        self.eval_default(ctx)
        if ctx.get_exited():
            ctx.restore(var_store)
        ctx.set_exited(False)
        ctx.tmp_forward_cond = forward_cond_copy
        # generate a nested set of if expressions per available action
        for cond, then_vars in action_exprs:
            merge_attrs(ctx, cond, then_vars)
Exemple #6
0
 def eval_cases(self, p4_state, cases):
     case_exprs = []
     case_matches = []
     context = p4_state.current_context()
     forward_cond_copy = context.tmp_forward_cond
     for case in reversed(cases.values()):
         var_store, contexts = p4_state.checkpoint()
         context.tmp_forward_cond = z3.And(forward_cond_copy, case["match"])
         case["case_block"].eval(p4_state)
         if not (context.has_returned or p4_state.has_exited):
             then_vars = p4_state.get_attrs()
             case_exprs.append((case["match"], then_vars))
         context.has_returned = False
         p4_state.has_exited = False
         p4_state.restore(var_store, contexts)
         case_matches.append(case["match"])
     var_store, contexts = p4_state.checkpoint()
     cond = z3.Not(z3.Or(*case_matches))
     context.tmp_forward_cond = z3.And(forward_cond_copy, cond)
     self.default_case.eval(p4_state)
     if context.has_returned or p4_state.has_exited:
         p4_state.restore(var_store, contexts)
     context.has_returned = False
     p4_state.has_exited = False
     context.tmp_forward_cond = forward_cond_copy
     for cond, then_vars in case_exprs:
         merge_attrs(p4_state, cond, then_vars)
Exemple #7
0
    def eval(self, p4_state):
        context = p4_state.current_context()
        cond = z3.simplify(p4_state.resolve_expr(self.cond))
        forward_cond_copy = context.tmp_forward_cond
        then_vars = None
        if not cond == z3.BoolVal(False):
            var_store, contexts = p4_state.checkpoint()
            context.tmp_forward_cond = z3.And(forward_cond_copy, cond)
            try:
                self.then_block.eval(p4_state)
            except ParserException:
                RejectState().eval(p4_state)
            if not (context.has_returned or p4_state.has_exited):
                then_vars = p4_state.get_attrs()
            p4_state.has_exited = False
            context.has_returned = False
            p4_state.restore(var_store, contexts)

        if not cond == z3.BoolVal(True):
            var_store, contexts = p4_state.checkpoint()
            context.tmp_forward_cond = z3.And(forward_cond_copy, z3.Not(cond))
            try:
                self.else_block.eval(p4_state)
            except ParserException:
                RejectState().eval(p4_state)
            if p4_state.has_exited or context.has_returned:
                p4_state.restore(var_store, contexts)
            p4_state.has_exited = False
            context.has_returned = False

        context.tmp_forward_cond = forward_cond_copy

        if then_vars:
            merge_attrs(p4_state, cond, then_vars)
Exemple #8
0
 def eval(self, p4_state):
     # boolean expressions can short-circuit
     # so we save the result of the right-hand expression and merge
     lval_expr = p4_state.resolve_expr(self.lval)
     var_store, chain_copy = p4_state.checkpoint()
     context = p4_state.current_context()
     forward_cond_copy = context.tmp_forward_cond
     context.tmp_forward_cond = z3.And(forward_cond_copy, lval_expr)
     rval_expr = p4_state.resolve_expr(self.rval)
     else_vars = p4_state.get_attrs()
     p4_state.restore(var_store, chain_copy)
     context.tmp_forward_cond = forward_cond_copy
     merge_attrs(p4_state, lval_expr, else_vars)
     return self.operator(lval_expr, rval_expr)
Exemple #9
0
    def eval(self, ctx, *args, **kwargs):
        merged_args = merge_parameters(self.params, *args, **kwargs)
        param_buffer, var_buffer = self.copy_in(ctx, merged_args)
        # only add the ctx after all the arguments have been resolved
        sub_ctx = LocalContext(ctx, var_buffer)
        # now we can set the arguments without influencing subsequent variables
        for param_name, param_val in param_buffer.items():
            sub_ctx.set_or_add_var(param_name, param_val)

        # execute the action expression with the new environment
        expr = self.eval_callable(sub_ctx, merged_args, var_buffer)
        self.call_counter += 1

        while sub_ctx.return_states:
            cond, return_attrs = sub_ctx.return_states.pop()
            merge_attrs(sub_ctx, cond, return_attrs)
        sub_ctx.copy_out(ctx)
        return expr
Exemple #10
0
    def eval(self, ctx):
        self.start_node.eval(ctx)
        counter = 0
        while counter < self.max_loop:
            parser_states = []
            terminal_nodes = self.terminal_nodes
            self.terminal_nodes = {}
            for parser_state, (cond, state) in terminal_nodes.items():
                sub_node = self.nodes[parser_state]
                # state forks here
                # FIXME
                dummy_ctx = LocalContext(ctx.master_ctx, {})
                dummy_ctx.locals = copy.deepcopy(state)
                dummy_ctx.tmp_forward_cond = cond
                sub_node.eval(dummy_ctx)
                parser_states.append((cond, dummy_ctx.get_attrs()))

            for cond, then_vars in parser_states:
                merge_attrs(ctx, cond, then_vars)
            counter += 1
Exemple #11
0
    def eval(self, p4_state):
        self.start_node.eval(p4_state)
        counter = 0
        while counter < self.max_loop:
            parser_states = []
            terminal_nodes = self.terminal_nodes
            self.terminal_nodes = {}
            for parser_state, (cond, state) in terminal_nodes.items():
                sub_node = self.nodes[parser_state]
                # state forks here
                dummy_context = P4Context({})
                dummy_context.locals = state
                dummy_context.tmp_forward_cond = cond
                p4_state.contexts.append(dummy_context)
                sub_node.eval(p4_state)
                parser_states.append((cond, p4_state.get_attrs()))
                p4_state.contexts.pop()

            for cond, then_vars in parser_states:
                merge_attrs(p4_state, cond, then_vars)
            counter += 1
Exemple #12
0
    def eval(self, p4_state, *args, **kwargs):
        merged_args = merge_parameters(self.params, *args, **kwargs)
        var_buffer = save_variables(p4_state, merged_args)
        param_buffer = self.copy_in(p4_state, merged_args)
        # only add the context after all the arguments have been resolved
        context = P4Context(var_buffer)
        p4_state.contexts.append(context)
        # now we can set the arguments without influencing subsequent variables
        for param_name, param_val in param_buffer.items():
            p4_state.set_or_add_var(param_name, param_val)

        # execute the action expression with the new environment
        expr = self.eval_callable(p4_state, merged_args, var_buffer)
        self.call_counter += 1

        while context.return_states:
            cond, return_attrs = context.return_states.pop()
            merge_attrs(p4_state, cond, return_attrs)
        context.copy_out(p4_state)
        p4_state.contexts.pop()
        return expr
Exemple #13
0
 def eval_cases(self, ctx, cases):
     case_exprs = []
     case_matches = []
     forward_cond_copy = ctx.tmp_forward_cond
     fall_through_matches = []
     for case_match, case_block in cases.values():
         # there is no block for the switch
         # this expressions falls through to the next switch case
         if not case_block:
             fall_through_matches.append(case_match)
             continue
         # matches the condition OR all the other fall-through switches
         case_match = z3.Or(case_match, *fall_through_matches)
         fall_through_matches.clear()
         var_store = ctx.checkpoint()
         ctx.tmp_forward_cond = z3.And(
             forward_cond_copy, case_match)
         case_block.eval(ctx)
         if not (ctx.has_returned or ctx.get_exited()):
             then_vars = ctx.get_attrs()
             case_exprs.append((case_match, then_vars))
         ctx.has_returned = False
         ctx.set_exited(False)
         ctx.restore(var_store)
         case_matches.append(case_match)
     var_store = ctx.checkpoint()
     # process the default expression
     cond = z3.Not(z3.Or(*case_matches))
     if not z3.is_false(cond):
         ctx.tmp_forward_cond = z3.And(forward_cond_copy, cond)
         self.default_case.eval(ctx)
         if ctx.has_returned or ctx.get_exited():
             ctx.restore(var_store)
         ctx.has_returned = False
         ctx.set_exited(False)
         ctx.tmp_forward_cond = forward_cond_copy
     # merge all the expressions in reverse order
     for cond, then_vars in reversed(case_exprs):
         merge_attrs(ctx, cond, then_vars)
Exemple #14
0
    def eval(self, p4_state):
        cond = z3.simplify(p4_state.resolve_expr(self.cond))

        # handle side effects for function and table calls
        if cond == z3.BoolVal(False):
            return p4_state.resolve_expr(self.else_val)
        if cond == z3.BoolVal(True):
            return p4_state.resolve_expr(self.then_val)

        var_store, chain_copy = p4_state.checkpoint()
        context = p4_state.current_context()
        forward_cond_copy = context.tmp_forward_cond
        context.tmp_forward_cond = z3.And(forward_cond_copy, cond)
        then_expr = p4_state.resolve_expr(self.then_val)
        then_vars = p4_state.get_attrs()
        p4_state.restore(var_store, chain_copy)
        context.tmp_forward_cond = forward_cond_copy

        else_expr = p4_state.resolve_expr(self.else_val)
        merge_attrs(p4_state, cond, then_vars)

        return handle_mux(cond, then_expr, else_expr)