p4c icon indicating copy to clipboard operation
p4c copied to clipboard

p4c-bmv2-ss doesn't support next operator in left part of assignment in a parser.

Open VolodymyrPeschanenkoIntel opened this issue 2 years ago • 6 comments

The p4c-bmv2-ss doesn't support operator next if left part of assignment. It finished with message: To repeat the problem, please, run the following command: ./p4c-bm2-ss "./res/next-def-use.json" ".../testdata/p4_16_samples/next-def-use.p4" It crashed here with the message:

p4c/testdata/p4_16_samples/next-def-use.p4(26): [--Werror=uninitialized] error: hdr.hs.next uninitialized: next field read
        hdr.hs.next = {8w0};
        ^^^^^^^^^^^

@antoninbas do you remember what is the BMv2 JSON code for assigning the .next stack field to an expression (not with extract)?

mihaibudiu avatar Jul 15 '22 18:07 mihaibudiu

@mbudiu-vmw I think a couple of operations are required:

  • size_stack will return the current size of the stack (so that's equivalent to using next).
  • dereference_header_stack (which supports l-values) will give you a reference to the header (hs.next)
  • after that a regular assign will work

as a reminder, you don't need to create temporary variables to hold intermediate results.

It should look more or less like this (I didn't validate it). The right operand for the assign can also be an expression of course.

{
    "op" : "assign",
    "parameters" : [
        {
            "type" : "expression",
            "value": {
                "type": "expression",
                "value": {
                    "op": "dereference_header_stack",
                    "left": {
                        "type": "header_stack",
                        "value": "hs"
                    },
                    "right": {
                        "type": "expression",
                        "value": {
                            "op": "size_stack",
                            "right": {
                                "type": "header_stack",
                                "value": "hs"
                            }
                        }
                    },
                }
            }
        },
        {
            "type" : "header",
            "value": {
            }
        }
    ]
}

antoninbas avatar Jul 15 '22 20:07 antoninbas

The problem is that this happens in a parser, so I need to use "set" instead of "assign", and set does not seem to support expressions for its arguments.

mihaibudiu avatar Jul 15 '22 23:07 mihaibudiu

How are "set" and "assign" different? Can we get rid of "set" and just use "assign" everywhere?

mihaibudiu avatar Jul 15 '22 23:07 mihaibudiu

hmmm so looking at the code, "set" supports expressions but only for the right operand.

but I forgot that there is the primitive operation which can be used and is more powerful than set. It is described in https://github.com/p4lang/behavioral-model/blob/main/docs/JSON_format.md#parser-operations and there is an example with assign_header:

"parser_ops": [
    {
        "op": "extract",
        "parameters": [
            {"type": "regular", "value": "ethernet"}
        ]
    },
    {
        "op": "primitive",
        "parameters": [
            {
                "op": "assign_header",
                "parameters": [
                    {"type": "header", "value": "ethernet_copy"},
                    {"type": "header", "value": "ethernet"},
                ]
            }
        ]
    }
]

The parameters can be expressions as well.

antoninbas avatar Jul 16 '22 00:07 antoninbas

note: primitive is strictly more powerful than set. I didn't remove set for backwards-compatibility and because set has a lot less overhead.

antoninbas avatar Jul 16 '22 00:07 antoninbas

I've hit a similar issue with the error message Parser 'set' operation has invalid destination type 'expression', expected 'field'.

What I want to do is essentially header_stack[variable_index] = value in parser, but set doesn't allow an expression on the LHS.

I see the restriction here is that in parser, LHS of assignment cannot be any expression other than header field access. I wonder if this restriction is a general one in P4, or a specific one to BMv2?

If it's specific to BMv2, what are the latest thoughts on relieving this restriction?

qobilidop avatar Oct 14 '23 00:10 qobilidop

hmmm so looking at the code, "set" supports expressions but only for the right operand.

but I forgot that there is the primitive operation which can be used and is more powerful than set. It is described in https://github.com/p4lang/behavioral-model/blob/main/docs/JSON_format.md#parser-operations and there is an example with assign_header:

"parser_ops": [
    {
        "op": "extract",
        "parameters": [
            {"type": "regular", "value": "ethernet"}
        ]
    },
    {
        "op": "primitive",
        "parameters": [
            {
                "op": "assign_header",
                "parameters": [
                    {"type": "header", "value": "ethernet_copy"},
                    {"type": "header", "value": "ethernet"},
                ]
            }
        ]
    }
]

The parameters can be expressions as well.

If I understand the doc and example correctly, the op contained in primitive can also be assign besides assign_header? And if p4c can generate code using primitive instead of set when assignment LHS is an expression, then the restriction is relieved?

qobilidop avatar Oct 14 '23 01:10 qobilidop

P4c could generate such code but it doesn't. It's a bug.

mihaibudiu avatar Oct 14 '23 01:10 mihaibudiu

Got it. I'll try to fix it as I have a use case that depends on this.

qobilidop avatar Oct 14 '23 01:10 qobilidop