Example #1
0
def dump_header_types(json_dict, hlir):
    header_types = []
    id_ = 0
    for name, p4_header in hlir.p4_headers.items():
        header_type_dict = OrderedDict()
        header_type_dict["name"] = name
        header_type_dict["id"] = id_
        id_ += 1

        fixed_width = 0
        for field, bit_width in p4_header.layout.items():
            if bit_width != p4.P4_AUTO_WIDTH:
                fixed_width += bit_width

        fields = []
        for field, bit_width in p4_header.layout.items():
            if bit_width == p4.P4_AUTO_WIDTH:
                bit_width = "*"
            fields.append([field, bit_width])
        header_type_dict["fields"] = fields

        length_exp = None
        max_length = None
        if p4_header.flex_width:
            length_exp = header_length_exp_format(p4_header.length,
                                                  zip(*fields)[0])
            # bm expects a length in bits
            length_exp = p4.p4_expression(length_exp, "*", 8)
            length_exp = p4.p4_expression(length_exp, "-", fixed_width)
            length_exp = dump_expression(length_exp)
            max_length = p4_header.max_length
        header_type_dict["length_exp"] = length_exp
        header_type_dict["max_length"] = max_length

        header_types.append(header_type_dict)

    json_dict["header_types"] = header_types
Example #2
0
def dump_header_types(json_dict, hlir):
    header_types = []
    id_ = 0
    for name, p4_header in hlir.p4_headers.items():
        header_type_dict = OrderedDict()
        header_type_dict["name"] = name
        header_type_dict["id"] = id_
        id_ += 1

        fixed_width = 0
        for field, bit_width in p4_header.layout.items():
            if bit_width != p4.P4_AUTO_WIDTH:
                fixed_width += bit_width

        fields = []
        for field, bit_width in p4_header.layout.items():
            if bit_width == p4.P4_AUTO_WIDTH:
                bit_width = "*"
            fields.append([field, bit_width])
        header_type_dict["fields"] = fields

        length_exp = None
        max_length = None
        if p4_header.flex_width:
            length_exp = header_length_exp_format(p4_header.length,
                                                  zip(*fields)[0])
            # bm expects a length in bits
            length_exp = p4.p4_expression(length_exp, "*", 8)
            length_exp = p4.p4_expression(length_exp, "-", fixed_width)
            length_exp = dump_expression(length_exp)
            max_length = p4_header.max_length
        header_type_dict["length_exp"] = length_exp
        header_type_dict["max_length"] = max_length

        header_types.append(header_type_dict)

    json_dict["header_types"] = header_types
Example #3
0
def header_length_exp_format(p4_expression, fields):
    def find_idx(name):
        for idx, field in enumerate(fields):
            if name == field:
                return idx
        return -1

    if type(p4_expression) is p4.p4_expression:
        new_expr = p4.p4_expression(op=p4_expression.op)
        new_expr.left = header_length_exp_format(p4_expression.left, fields)
        new_expr.right = header_length_exp_format(p4_expression.right, fields)
        return new_expr
    elif type(p4_expression) is str:  # refers to field in same header
        idx = find_idx(p4_expression)
        assert (idx >= 0)
        # trick so that dump_expression uses local for this
        return p4.p4_signature_ref(idx)
    else:
        return p4_expression
Example #4
0
def header_length_exp_format(p4_expression, fields):

    def find_idx(name):
        for idx, field in enumerate(fields):
            if name == field:
                return idx
        return -1

    if type(p4_expression) is p4.p4_expression:
        new_expr = p4.p4_expression(op=p4_expression.op)
        new_expr.left = header_length_exp_format(p4_expression.left, fields)
        new_expr.right = header_length_exp_format(p4_expression.right, fields)
        return new_expr
    elif type(p4_expression) is str:  # refers to field in same header
        idx = find_idx(p4_expression)
        assert(idx >= 0)
        # trick so that dump_expression uses local for this
        return p4.p4_signature_ref(idx)
    else:
        return p4_expression
Example #5
0
def valid_expression(hi):
    if isinstance(hi, p4.p4_field): hi = hi.instance
    return p4.p4_expression(None, "valid", hi)
Example #6
0
def dump_actions(json_dict, hlir):
    actions = []
    action_id = 0

    table_actions_set = set()
    for _, table in hlir.p4_tables.items():
        for action in table.actions:
            table_actions_set.add(action)

    for action in table_actions_set:
        action_dict = OrderedDict()
        action_dict["name"] = action.name
        action_dict["id"] = action_id
        action_id += 1

        runtime_data = []
        param_with_bit_widths = OrderedDict()
        for param, width in zip(action.signature, action.signature_widths):
            if not width:  # pragma: no cover
                LOG_CRITICAL("unused parameter in action def")
            param_with_bit_widths[param] = width

            param_dict = OrderedDict()
            param_dict["name"] = param
            param_dict["bitwidth"] = width
            runtime_data.append(param_dict)
        action_dict["runtime_data"] = runtime_data

        primitives = []
        for call in action.flat_call_sequence:
            primitive_dict = OrderedDict()

            primitive_name = call[0].name
            primitive_dict["op"] = primitive_name

            args = call[1]

            # backwards compatibility with older P4 programs
            if primitive_name == "modify_field" and len(args) == 3:
                LOG_WARNING(
                    "Your P4 program uses the modify_field() action primitive "
                    "with 3 arguments (aka masked modify), bmv2 does not "
                    "support it anymore and this compiler will replace your "
                    "modify_field(a, b, c) with "
                    "modify_field(a, (a & ~c) | (b & c))")
                Lexpr = p4.p4_expression(args[0], "&",
                                         p4.p4_expression(None, "~", args[2]))
                Rexpr = p4.p4_expression(args[1], "&", args[2])
                new_arg = p4.p4_expression(Lexpr, "|", Rexpr)
                args = [args[0], new_arg]

            primitive_args = []
            for arg in args:
                arg_dict = OrderedDict()
                if type(arg) is int or type(arg) is long:
                    arg_dict["type"] = "hexstr"
                    arg_dict["value"] = hex(arg)
                elif type(arg) is p4.p4_field:
                    arg_dict["type"] = "field"
                    arg_dict["value"] = format_field_ref(arg)
                elif type(arg) is p4.p4_header_instance:
                    arg_dict["type"] = "header"
                    arg_dict["value"] = arg.name
                elif type(arg) is p4.p4_signature_ref:
                    arg_dict["type"] = "runtime_data"
                    arg_dict["value"] = arg.idx
                elif type(arg) is p4.p4_field_list:
                    # hack for generate_digest calls
                    if primitive_name == "generate_digest":
                        id_ = field_list_to_learn_id(arg)
                    elif "clone" in primitive_name or\
                         primitive_name in {"resubmit", "recirculate"}:
                        id_ = field_list_to_id(arg)
                    arg_dict["type"] = "hexstr"
                    arg_dict["value"] = hex(id_)
                elif type(arg) is p4.p4_field_list_calculation:
                    arg_dict["type"] = "calculation"
                    arg_dict["value"] = arg.name
                elif type(arg) is p4.p4_meter:
                    arg_dict["type"] = "meter_array"
                    arg_dict["value"] = arg.name
                elif type(arg) is p4.p4_counter:
                    arg_dict["type"] = "counter_array"
                    arg_dict["value"] = arg.name
                elif type(arg) is p4.p4_register:
                    arg_dict["type"] = "register_array"
                    arg_dict["value"] = arg.name
                elif type(arg) is p4.p4_expression:
                    arg_dict["type"] = "expression"
                    arg_dict["value"] = dump_expression(arg)
                else:  # pragma: no cover
                    LOG_CRITICAL("action arg type is not supported: ",
                                 type(arg))

                if primitive_name in {"push", "pop"} and\
                   arg_dict["type"] == "header":
                    arg_dict["type"] = "header_stack"
                    arg_dict["value"] = re.sub(r'\[.*\]', '',
                                               arg_dict["value"])

                primitive_args.append(arg_dict)
            primitive_dict["parameters"] = primitive_args

            primitives.append(primitive_dict)

        action_dict["primitives"] = primitives

        actions.append(action_dict)

    json_dict["actions"] = actions
Example #7
0
def dump_actions(json_dict, hlir):
    actions = []
    action_id = 0

    table_actions_set = set()
    for _, table in hlir.p4_tables.items():
        for action in table.actions:
            table_actions_set.add(action)

    for action in table_actions_set:
        action_dict = OrderedDict()
        action_dict["name"] = action.name
        action_dict["id"] = action_id
        action_id += 1

        runtime_data = []
        param_with_bit_widths = OrderedDict()
        for param, width in zip(action.signature, action.signature_widths):
            if not width:  # pragma: no cover
                LOG_CRITICAL("unused parameter in action def")
            param_with_bit_widths[param] = width

            param_dict = OrderedDict()
            param_dict["name"] = param
            param_dict["bitwidth"] = width
            runtime_data.append(param_dict)
        action_dict["runtime_data"] = runtime_data

        primitives = []
        for call in action.flat_call_sequence:
            primitive_dict = OrderedDict()

            primitive_name = call[0].name
            primitive_dict["op"] = primitive_name

            args = call[1]

            # backwards compatibility with older P4 programs
            if primitive_name == "modify_field" and len(args) == 3:
                LOG_WARNING(
                    "Your P4 program uses the modify_field() action primitive "
                    "with 3 arguments (aka masked modify), bmv2 does not "
                    "support it anymore and this compiler will replace your "
                    "modify_field(a, b, c) with "
                    "modify_field(a, (a & ~c) | (b & c))")
                Lexpr = p4.p4_expression(args[0], "&",
                                         p4.p4_expression(None, "~", args[2]))
                Rexpr = p4.p4_expression(args[1], "&", args[2])
                new_arg = p4.p4_expression(Lexpr, "|", Rexpr)
                args = [args[0], new_arg]

            primitive_args = []
            for arg in args:
                arg_dict = OrderedDict()
                if type(arg) is int or type(arg) is long:
                    arg_dict["type"] = "hexstr"
                    arg_dict["value"] = hex(arg)
                elif type(arg) is p4.p4_field:
                    arg_dict["type"] = "field"
                    arg_dict["value"] = format_field_ref(arg)
                elif type(arg) is p4.p4_header_instance:
                    arg_dict["type"] = "header"
                    arg_dict["value"] = arg.name
                elif type(arg) is p4.p4_signature_ref:
                    arg_dict["type"] = "runtime_data"
                    arg_dict["value"] = arg.idx
                elif type(arg) is p4.p4_field_list:
                    # hack for generate_digest calls
                    if primitive_name == "generate_digest":
                        id_ = field_list_to_learn_id(arg)
                    elif "clone" in primitive_name or\
                         primitive_name in {"resubmit", "recirculate"}:
                        id_ = field_list_to_id(arg)
                    arg_dict["type"] = "hexstr"
                    arg_dict["value"] = hex(id_)
                elif type(arg) is p4.p4_field_list_calculation:
                    arg_dict["type"] = "calculation"
                    arg_dict["value"] = arg.name
                elif type(arg) is p4.p4_meter:
                    arg_dict["type"] = "meter_array"
                    arg_dict["value"] = arg.name
                elif type(arg) is p4.p4_counter:
                    arg_dict["type"] = "counter_array"
                    arg_dict["value"] = arg.name
                elif type(arg) is p4.p4_register:
                    arg_dict["type"] = "register_array"
                    arg_dict["value"] = arg.name
                elif type(arg) is p4.p4_expression:
                    arg_dict["type"] = "expression"
                    arg_dict["value"] = dump_expression(arg)
                else:  # pragma: no cover
                    LOG_CRITICAL("action arg type is not supported: ",
                                 type(arg))

                if primitive_name in {"push", "pop"} and\
                   arg_dict["type"] == "header":
                    arg_dict["type"] = "header_stack"
                    arg_dict["value"] = re.sub(r'\[.*\]', '', arg_dict["value"])

                primitive_args.append(arg_dict)
            primitive_dict["parameters"] = primitive_args

            primitives.append(primitive_dict)

        action_dict["primitives"] = primitives

        actions.append(action_dict)

    json_dict["actions"] = actions