Closed ghost closed 4 years ago
jafingerhut@ antoninbas@ stefanheule@ please take a look
I think you mean @jafingerhut @antoninbas @stefanheule :)
Should the snd_string and sdn_bitwidth be a oneof (at least conceptually, maybe not for back-wards compatibility reasons; though we should still document it)?
It will probably need to be "string"
since this annotation expects a valid expression (at least as it is currently implemented in p4c).
I agree with @stefanheule that we should use a oneof
, since in this specific case it is actually backwards-compatible (https://developers.google.com/protocol-buffers/docs/proto3#backwards-compatibility-issues):
Move fields into or out of a oneof: You may lose some of your information (some fields will be cleared) after the message is serialized and parsed. However, you can safely move a single field into a new oneof and may be able to move multiple fields if it is known that only one is ever set.
Using "string"
instead of string
in the P4_16 source code does seem likely to make it a bit easier to implement in p4c.
oneof
also seems like a good idea, assuming that is a backwards compatible change (I do not know Protobuf rules well enough to say).
I have been trying to get a v1model P4_16 program using @p4runtime_translation
to generate a non-empty type_info
message. It is definitely possible, because this p4c test program has one, but because of struct types and enum types, not because of a type
definition:
I have not been able to find a way to get p4c to generate a non-empty type type_info
message for a program that uses a type definition like this one, though, using a field of that type as a table search key field:
@p4runtime_translation("com.fingerhutpress/andysp4arch/v1/IPv4Addr_t", 32)
type bit<32> IPv4Addr_t;
Does anyone else know how? Or perhaps the p4c P4Info writing code does not handle this case yet?
Here is a small public test program you can experiment with, if it helps:
Submitted an issue for p4c crash for one test program I tried with a custom type
definition that should affect P4Info file contents, here: https://github.com/p4lang/p4c/issues/2234
Not relevant for how to change P4Info message formats, but for getting p4c to produce correct P4Info files for things already defined, before this issue was created.
Took a look at the compiler implementation today, and it looks to me like we have 2 reasonable choices, as discussed in previous comments:
@p4runtime_translation
in the compiler: https://github.com/p4lang/p4c/blob/master/control-plane/p4RuntimeSerializer.cpp#L723. The annotation expects 2 valid P4 expressions: the first one is later converted to a string literal, and the second one to an integer literal. We can be more "liberal" for the second one, and start accepting string literals which encode a supported type ("bit<W>"
, "int<W>"
, "string"
).@p4runtime_translation
and "parse" the annotation tokens ourselves. In practice, that just means that the compiler will pass the annotations to us as "raw" strings, and we have to validate their contents, which for this specific case should not be too much trouble.Both solutions would be backwards-compatible.
Solution 2) would enable us to write @p4runtime_translation("p4.org/psa/v1/PortId_t", string)
and @p4runtime_translation("p4.org/psa/v1/PortId_t", bit<32>)
instead of @p4runtime_translation("p4.org/psa/v1/PortId_t", "string")
and @p4runtime_translation("p4.org/psa/v1/PortId_t", "bit<32>")
, at the price of marginally more work.
@konne88 @stefanheule I would like to know what the "optimal" solution would be for you (doesn't have to be one of these 2)? It doesn't seem likely that we can extend the annotation-parsing infrastructure in the compiler in such a way that it can validate for us that the second argument is a valid P4 type. That looks like a lot of work, just for our specific case. I myself am not familiar at all with that part of the p4c code base. But even if we could have that, is it really the best solution for our use-case? The second argument is not really meant to be a P4 type. It is purely a control-plane type and it never shows up in the P4 datapath. This type information is used purely to transmit information over P4Runtime.
I know that we have been talking about disabling translation for bmv2 to get useful human-readable logs, but even that is likely to require changes to bmv2's logging architecture. And bmv2 only understands binary strings. IMO, the "right" way to achieve the same thing is by using some kind of identity translation with a large underlying type:
@p4runtime_translation("p4.org/psa-extensions/v1/GroupId_t", "string")
type bit<1024> GroupId_t;
I think using @p4runtime_translation("p4.org/psa/v1/PortId_t", string)
and @p4runtime_translation("p4.org/psa/v1/PortId_t", bit<32>)
(and @p4runtime_translation("p4.org/psa/v1/PortId_t", 32)
which is deprecated but supported for backwards compatibility) is nicest.
It's a good observation though that the argument isn't a P4 type necessarily, but a controlplane type (the two type systems aren't necessarily the same), but it also seems like using string
and bit<w>
is convenient for us.
I'm not sure what you mean by the right way to do this in bmv2. I agree that your example of using 1024 bits will probably just work, but I imagine the "right" way to do this is to support the translations in bmv2 and have an option to instead just use the controlplane type in bmv2 (i.e., support strings in bmv2).
@stefanheule Basically there has to be an underlying bit<W>
type for it to be a correct program. P4 does not support string manipulations in the datapath and you cannot have variables (e.g. metadata fields) with type string
and match on them in tables. Given this, bmv2 is still going to be using the underlying type, not the control plane type (which is not a P4 type per se). I don't think it is realistic, or even a good idea, to add complexity to bmv2 to handle these annotated types completely differently. Today bmv2 handles all non-compound types as bitstrings (or rather a combination of a bitsring + an arbitrary-precision integer), and does not know anything about user-defined type
s. However, it will probably be possible to improve logging for match fields & action parameters with an associated string
control-plane type: instead of logging the values as hexadecimal strings, we can probably log them as human-readable strings if we include some additional information in the bmv2 JSON.
Referring to objects by a string name instead of an integer id makes P4RT flows a lot more readable, which for example greatly helps with debugging. We therefore propose to generalize the
@p4runtime_translation
annotation, to not just support fixed bit width integers, but also strings.So in addition to:
We propose to also support:
Since values are already represented as
bytes
in P4RT messages, there is no need for any changes of those protos.However, we do need to change the P4Info definition. Currently,
match_fields
and actionparams
refer to translated values as follows:To support strings, we propose extending the
new_types
proto in https://github.com/p4lang/p4runtime/blob/master/proto/p4/config/v1/p4types.proto as follows:So in the above example, the P4Info would be:
When translating from a string, the
bitwidth
field inmatch_fields
and actionparams
is ignored.