-
Notifications
You must be signed in to change notification settings - Fork 80
Named Parameters
The goal of this proposal is to extend the syntax of P4_16 to support named parameters to controls, tables, actions, externs, and packages. The main motivation is to enable optional parameters to enable reducing the overhead of listing all parameters and limit the ordering constraints.
The p4c compiler currently supports optional parameters as an experimental feature. This is enabled
by the @optional
annotation followed by an ordered list of arguments. That is, if an optional
argument is present, all preceeding arguments (non-optional and optional) must be present. Optional
arguments apply to extern methods.
We propose the following changes:
- Calls specify parameters by name. By default, all parameters must be specified.
- Optional parameters are specified by assigning a default parameter value:
param_modifier param_type name = default_parameter_value
- We allow specifying
_
as the default value and the compiler will initialize the optional parameter with an appropriate value. - Mandatory parameters must preceed all optional parameters and all parameters must be called in the order in which they were declared. This is similar to C++, except that preceeding optional parameters can be fully omitted (as in Python).
- We only allow optional parameters for some kinds of functions:
- Constructors, including extern constructors and package constructors, controls, and parsers
- Extern methods
- The proposal is restricted to entities that are not exposed at runtime, i.e., control plane APIs do not support optional parameters
- Optional parameters must be either
in
or directionless
Discussion on 4/16:
- explicitly say controls and parser at runtime
- why do we restrict to non-control plane APIs visible entities?
- requires language bindings in the API
- done for simplicity
- where are the default (don't care) values defined.
- expand the example for to include control
- action params: what does the '_' mean?
- how about things that produce an out value?
- mixing named/unnamed parameters -- clear description of restrictions
- examples on invocations
- overloading
- Mihai to give some examples
If accepted, the current @optional
experimental feature will be deprecated in favor of this
proposal.
- The need for defining a
None
value.
Current declarations of IngressParser in PSA:
parser IngressParser<H, M, RESUBM, RECIRCM>(
packet_in buffer,
out H parsed_hdr,
inout M user_meta,
in psa_ingress_parser_input_metadata_t istd,
in RESUBM resubmit_meta,
in RECIRCM recirculate_meta);
Implementation of IngressParser in psa-example-counters.p4, when the parser does not handle resubmit or recirculate:
parser IngressParserImpl(
packet_in buffer,
out headers parsed_hdr,
inout metadata user_meta,
in psa_ingress_parser_input_metadata_t istd,
in empty_metadata_t resubmit_meta,
in empty_metadata_t recirculate_meta)
Implementation of IngressParser in psa-example-resubmit.p4, when the parser only implements resubmit:
parser IngressParserImpl(
packet_in buffer,
out headers parsed_hdr,
inout metadata user_meta,
in psa_ingress_parser_input_metadata_t istd,
in resubmit_metadata_t resub_meta,
in empty_metadata_t recirculate_meta) { ... }
With proposed named parameters, the declaration makes the resubmit_meta
and recirculate_meta
named parameters, with default values.
Declaration:
parser IngressParser<H, M, RESUBM, RECIRCM>(
packet_in buffer,
out H parsed_hdr,
inout M user_meta,
in psa_ingress_parser_input_metadata_t istd,
in RESUBM resubmit_meta = _,
in RECIRCM recirculate_meta = _);
The counter example implementation declaration becomes:
parser IngressParserImpl(
packet_in buffer,
out headers parsed_hdr,
inout metadata user_meta,
in psa_ingress_parser_input_metadata_t istd) { ... }
The resubmit example implementation declaration becomes:
parser IngressParserImpl(
packet_in buffer,
out headers parsed_hdr,
inout metadata user_meta,
in psa_ingress_parser_input_metadata_t istd)
in resubmit_metadata_t resubmit_meta) { ... }
The Register
extern in PSA is declared as:
extern Register<T, S> {
Register(bit<32> size);
Register(bit<32> size, T initial_value);
}
With named parameters, the definition can become:
extern Register<T, S> {
Register(bit<32> size, T initial_value = 0);
}
The PSA package definition is:
package PSA_Switch<IH, IM, EH, EM, NM, CI2EM, CE2EM, RESUBM, RECIRCM> (
IngressPipeline<IH, IM, NM, CI2EM, RESUBM, RECIRCM> ingress,
PacketReplicationEngine pre,
EgressPipeline<EH, EM, NM, CI2EM, CE2EM, RECIRCM> egress,
BufferingQueueingEngine bqe);
If we want a PSA-compatible program without an egress pipeline, we still have to declare all the Egress related controls (as empty) and instantiate an egress pipeline. With named arguments, the declaration can be:
package PSA_Switch<IH, IM, EH, EM, NM, CI2EM, CE2EM, RESUBM, RECIRCM> (
IngressPipeline<IH, IM, NM, CI2EM, RESUBM, RECIRCM> ingress,
PacketReplicationEngine pre = _,
EgressPipeline<EH, EM, NM, CI2EM, CE2EM, RECIRCM> egress = _,
BufferingQueueingEngine bqe = _);
And thus one can instantiate any combination of the pipeline without the need of instantiating all the controls:
PSA_Switch(my_ingress) main;
Moreover, since the pre
and bqe
are instantiated by default by the architecture, we can remove the need of macro hacks, and declare the switch:
PSA_Switch(ingress = my_ingress, egress = my_egress) main;