p4c
p4c copied to clipboard
p4c-bmv2-ss doesn't support next operator in left part of assignment in a parser.
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)?
@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 usingnext
). -
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": {
}
}
]
}
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.
How are "set" and "assign" different? Can we get rid of "set" and just use "assign" everywhere?
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.
note: primitive
is strictly more powerful than set
. I didn't remove set
for backwards-compatibility and because set
has a lot less overhead.
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?
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 thanset
. It is described in https://github.com/p4lang/behavioral-model/blob/main/docs/JSON_format.md#parser-operations and there is an example withassign_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 beexpressions
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?
P4c could generate such code but it doesn't. It's a bug.
Got it. I'll try to fix it as I have a use case that depends on this.